公司在搭建docker自动化部署时,需要制作一个nginx镜像在其docker run时通过外部指定环境变量使得容器中的配置文件自动生成,不需要再到容器里改配置文件。

实现思路

最后运行的命令大概是这样:

docker run -d -p 80:80 -e xxx=xx 镜像名称 镜像中脚本路径

这里的脚本会代替dockerfile中的CMD指令,所以我们要构建一个自动生成且启动nginx的shell脚本。

#!/bin/bash#从环境变量里面获取lt开头,为了与其他环境变量区别开,例如lt_analysis=172.17.0.1:8083result=""for a in $(env | grep ^lt)do OLD_IFS="$IFS" IFS="_" arr=($a) b=${arr[1]} IFS="=" arr=($b) IFS="$OLD_IFS" result="${result}  location /${arr[0]}/ {    proxy_pass  http://${arr[1]}/${arr[0]}/;    proxy_connect_timeout 90;    proxy_send_timeout 90;    proxy_read_timeout 90;  }"done#将nginx配置文件中nginx_conf中置换成变量resultsed -i "s|nginx_conf|$(echo ${result})|g" /etc/nginx/nginx.confcd /usr/sbin./nginx

需要说明的一点是业务中并不需要将整个配置文件生成,只需要将其中location生成然后替换原配置文件中标记的位置,下面就是原配置文件标记的位置。

http {  ...    server {    ...    location / {      root  html;      index index.html index.htm;    }    nginx_conf    #error_page 404       /404.html;    ...

我以为将这个shell脚本和默认的配置文件放入nginx的dockerfile镜像中,然后就成功了,但是...运行上述命令之后容器没有起来,查看容器日志,出来的信息却是***Syntax error: “(” unexpected***。我的shell脚本在centos上经过测试是可以运行的,那么为什么会报这个错呢? 经过排查,原来是dockerfile使用基础镜像是官方nginx,官方的镜像使用Ubuntu不再使用bash来而是dash执行shell脚本,真是个坑 。没办法我只好修改dockerfile,下面就是使用基础镜像centos。

FROM centosENV NGINX_VERSION 1.10.3ENV OPENSSL_VERSION 1.0.2kENV PCRE_VERSION 8.40ENV ZLIB_VERSION 1.2.11ENV BUILD_ROOT /usr/local/xx/nginx# 为了减小最终生成的镜像占用的空间,这里没有执行yum update命令,可能不是好的实践# 为了加快构建速度,这里使用了163的安装源#RUN yum -y update /RUN yum -y install curl /  && mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup /  && curl http://mirrors.163.com/.help/CentOS7-Base-163.repo -o /etc/yum.repos.d/CentOS7-Base-163.repo /   && yum -y install gcc gcc-c++ make perl zip unzip /  && mkdir -p $BUILD_ROOT /  && cd $BUILD_ROOT /  && curl https://ftp.pcre.org/pub/pcre/pcre-$PCRE_VERSION.zip -o $BUILD_ROOT/pcre-$PCRE_VERSION.zip /  && curl https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz -o $BUILD_ROOT/openssl-$OPENSSL_VERSION.tar.gz /  && curl http://www.zlib.net/zlib-$ZLIB_VERSION.tar.gz -o $BUILD_ROOT/zlib-$ZLIB_VERSION.tar.gz /  && curl https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o $BUILD_ROOT/nginx-$NGINX_VERSION.tar.gz /  && tar vxzf nginx-$NGINX_VERSION.tar.gz /  && unzip pcre-$PCRE_VERSION.zip /  && tar vxfz zlib-$ZLIB_VERSION.tar.gz /  && tar vxfz openssl-$OPENSSL_VERSION.tar.gz /  && cd nginx-$NGINX_VERSION /  && BUILD_CONFIG="/    --prefix=/etc/nginx /    --sbin-path=/usr/sbin/nginx /    --conf-path=/etc/nginx/nginx.conf /    --error-log-path=/var/log/nginx/error.log /    --http-log-path=/var/log/nginx/access.log /    --pid-path=/var/run/nginx.pid /    --lock-path=/var/run/nginx.lock /    --http-client-body-temp-path=/var/cache/nginx/client_temp /    --http-proxy-temp-path=/var/cache/nginx/proxy_temp /    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp /    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp /    --http-scgi-temp-path=/var/cache/nginx/scgi_temp /    --with-openssl=$BUILD_ROOT/openssl-$OPENSSL_VERSION /    --with-pcre=$BUILD_ROOT/pcre-$PCRE_VERSION /    --with-zlib=$BUILD_ROOT/zlib-$ZLIB_VERSION /    --with-http_ssl_module /    --with-http_v2_module /     --with-threads /    " /  && mkdir -p /var/cache/nginx /  && ./configure $BUILD_CONFIG /  && make && make install /  && rm -rf $BUILD_ROOT /  && yum -y remove gcc gcc-c++ make perl zip unzip /  && yum clean all#替换nginx默认文件COPY nginx.conf /etc/nginx/#添加自动生成配置文件的shell脚本COPY 脚本名称 /root/#暴露端口EXPOSE 80 443CMD ["nginx", "-g", "daemon off;"]

提醒:docker容器不支持后台运行,当命令执行之后,容器也会自然退出,这里我们需要将nginx配置文件设置一下

#user nobody;worker_processes 1;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid    logs/nginx.pid;daemon off;  //这里添加,关闭后台运行events {  worker_connections 1024;}http {