业务镜像的编写————Dockerfile篇

基础镜像,接触docker的人基本上都知道这个概念,用来跑业务,跑环境的基础,举个例子:java业务的需要用到java环境的基础镜像,一般会在镜像使用的时候选择:

java:8或者apline-java:8或者openjdk:8之类的,如果业务要求没有特别高的情况下,一般都是采用官方写好的镜像,毕竟官方优化要比我们自己写和自己优化要好很多。

而在这里,我要提出的是一个特殊的情况,比如一开始就定下的代码运行目录,一开始就决定好的读取代码目录的顺序等等,这种对镜像中某些路径和目录有特殊要求的情况,如果单单使用官方的镜像,在很多地方要遵循官方镜像的编写原则,更改自己的代码,在代码量比较大或者代码模块较多的情况下,会增加很大的工作量。在这个时候就需要自己编写属于自己的业务基础镜像,集成定制属于自己的镜像,当然你也可以基于官方镜像进行更改或者commit。在很多情况下,方便管理和便于修改是硬需求,于是通过Dockerfile的方式生成业务基础镜像的方式,要比commit好很多。以下是我写的一个例子,基于centos7编写的php+nginx的基础镜像(友情提示,写Dockerfile最好是熟悉各种linux的安装方式):

FROM centos:7   #这里是基于centos系列的基础镜像做的包,如果只写centos很有可能拉取的是centos8
MAINTAINER adif0028<longliu2long@163.com>    #写明作者,这句可有可无
COPY ustc.repo /etc/yum.repos.d/ustc.repo    #以下几个copy是把下载好和已经配置好的东西放到刚需目录和路径下。下面会有个公共目录放复制进去的东西和下载的东西。
COPY run.sh /run.sh
COPY php.ini /usr/local/php/etc/php.ini
COPY php-fpm.conf /usr/local/php/etc/php-fpm.conf
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
COPY index.php /usr/local/nginx/html/index.php
COPY www-php.conf /usr/local/php/etc/php-fpm.d/www-php.conf
COPY rsyslog.conf /etc/rsyslog.conf
COPY php-7.0.31.tar.gz /data/php-7.0.31.tar.gz   #这里是指定自己所需的php版本,可以在线下载,我是嫌下载太慢自己本地拷贝进去
RUN yum repolist && yum install wget -y && cd /data && tar -xf php-7.0.31.tar.gz \
    && mv /etc/yum.repos.d/CentOS-* /data && yum clean all && yum repolist && yum install nc -y && yum install rsyslog -y && yum install ImageMagick-devel -y \
    && yum install libssh2-devel -y && yum install gcc-c++ -y && yum install cyrus-sasl-devel -y \
    && wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo && yum repolist && yum install autoconf -y \
    && wget http://nginx.org/download/nginx-1.16.1.tar.gz && wget https://pecl.php.net/get/msgpack-2.0.2.tgz && wget https://pecl.php.net/get/yar-2.0.4.tgz && wget https://pecl.php.net/get/yaconf-1.0.7.tgz \
    && wget https://pecl.php.net/get/redis-4.1.0.tgz && wget https://pecl.php.net/get/imagick-3.4.3.tgz && wget https://pecl.php.net/get/swoole-4.0.2.tgz \
    && wget https://pecl.php.net/get/ssh2-1.1.2.tgz && wget https://pecl.php.net/get/mongodb-1.5.3.tgz && wget https://pecl.php.net/get/grpc-1.19.0.tgz \
    && wget https://pecl.php.net/get/protobuf-3.7.1.tgz && wget https://pecl.php.net/get/SeasClick-0.1.0.tgz \
    && yum install gcc -y && yum install libxml2-devel -y && yum install openssl-devel -y && yum install curl-devel -y && yum install libjpeg-devel -y \
    && yum install libpng-devel -y && yum install libXpm-devel -y && yum install freetype-devel -y && yum install libmcrypt-devel -y && yum install make -y \     #以上是更换yum源,安装php所需依赖和业务所需php模块
    && cd /data/php-7.0.31 \     #这里就是公共目录里的php了。
    && CONFIG="\                 #Dockerfile是支持变量定义的,这里是定义了php的安装路径等变量。
        --prefix=/usr/local/php \
        --with-config-file-path=/usr/local/php/etc \
        --with-config-file-scan-dir=/usr/local/php/etc/php.d \
        --disable-ipv6 \
        --enable-bcmath \
        --enable-calendar \
        --enable-exif \
        --enable-fpm \
        --with-fpm-user=www \
        --with-fpm-group=www \
        --enable-ftp \
        --enable-gd-jis-conv \
        --enable-gd-native-ttf \
        --enable-inline-optimization \
        --enable-mbregex \
        --enable-mbstring \
        --enable-mysqlnd \
        --enable-opcache \
        --enable-pcntl \
        --enable-shmop \
        --enable-soap \
        --enable-sockets \
        --enable-static \
        --enable-sysvsem \
        --enable-wddx \
        --enable-xml \
        --with-curl \
        --with-gd \
        --with-jpeg-dir \
        --with-freetype-dir \
        --with-xpm-dir \
        --with-png-dir \
        --with-gettext \
        --with-iconv \
        --with-libxml-dir \
        --with-mcrypt \
        --with-mhash \
        --with-mysqli \
        --with-pdo-mysql \
        --with-pear \
        --with-openssl \
        --with-xmlrpc \
        --with-zlib \
        --disable-debug \
        --disable-phpdbg \
         " \
    && CONFIGU="\                  #这里是定义了nginx安装路径等等相关变量
        --prefix=/usr/local/nginx \
        --sbin-path=/usr/sbin/nginx \
        --modules-path=/usr/lib/nginx/modules \
        --conf-path=/usr/local/nginx/conf/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 \
        --user=www \
        --group=www \
        --with-http_stub_status_module \
        --with-http_v2_module \
        --with-ipv6 \
        --with-http_gzip_static_module \
        --with-http_realip_module \
        --with-http_flv_module \
        --with-http_ssl_module \
          " \
    && ./configure $CONFIG \        #注意上下文的变量对应,进行config编译。记住一定要在源码目录里进行
    && make && make install \       #编译安装。
    #&& /usr/local/php/bin/pear install channel://pear.php.net/PHP_Archive-0.12.0 \  #这一步其实是针对php的一个排错,但是由于网络原因导致这里经常卡掉镜像,我就去掉了因为不影响使用。
    && cp /data/php-7.0.31/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm && chmod a+x /etc/init.d/php-fpm && cp /usr/local/php/bin/php /usr/sbin/ \
    && groupadd -r www && useradd -r -g www -s /bin/false -M www && cd /data/php-7.0.31/ext/zip && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data/php-7.0.31/ext/opcache && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf msgpack-2.0.2.tgz && cd /data/msgpack-2.0.2 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf yar-2.0.4.tgz && cd /data/yar-2.0.4 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf yaconf-1.0.7.tgz && cd /data/yaconf-1.0.7 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf redis-4.1.0.tgz && cd /data/redis-4.1.0 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf imagick-3.4.3.tgz && cd /data/imagick-3.4.3 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf swoole-4.0.2.tgz && cd /data/swoole-4.0.2 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf ssh2-1.1.2.tgz && cd /data/ssh2-1.1.2 &&  /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf mongodb-1.5.3.tgz && cd /data/mongodb-1.5.3 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf protobuf-3.7.1.tgz && cd /data/protobuf-3.7.1 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf grpc-1.19.0.tgz && cd /data/grpc-1.19.0 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \
    && cd /data && tar -xf SeasClick-0.1.0.tgz && cd /data/SeasClick-0.1.0 && /usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config && make && make install \ 
#这里往上是创建了一个www用户,然后php模块的编译安装 && mkdir -p /home/wwwlogs/phplog/ && chown -R www:www /home/wwwlogs/phplog/ && mkdir -p /usr/local/nginx/html && chmod a+x /run.sh && mkdir -p /var/cache/nginx \ #这里有个run.sh我会在后面放出来做解释 && chown www:www -R /var/cache/nginx && chown www:www -R /usr/local/nginx \ && cd /data && tar -xf nginx-
1.16.1.tar.gz && cd /data/nginx-1.16.1 \ && ./configure $CONFIGU \ && make && make install \
#这里是nginx的安装了 && yum remove perl -y && yum remove wget -y && yum remove gcc -y && yum remove make -y \ && yum remove autoconf -y && yum remove gcc-c++ -y && yum remove kernel-headers -y && yum remove cpp -y && yum clean all && rm -rf /data
/* #删掉一些不影响的功能和数据包,精简镜像 EXPOSE 80 #暴露端口 ENTRYPOINT ["/run.sh"] #执行run.sh CMD ["/bin/sh","-c"] #指定运行bash

上面我做了大概步骤的注释,写Dockerfile优化并且减少体积技巧是:

1,尽量减少RUN层数,增加一层就会使镜像的体积增大不少,我这里只写了一个RUN。不过这一层的RUN也挺大的。

2,因为是centos,基础镜像解压之后200多m,所以尽量的减少依赖的安装。用以减少Dockerfile的体积。

3,除却必要的配置文件,一定要去掉不必要的文件在里面,COPY进去或者下载好的包,安装完成源包删掉,然后清除掉缓存。

4,删掉不必要的组件,比如上例最后,我会删掉不常用或者有漏洞或者删掉不影响镜像使用的包。就像里面的gcc之类的。

5,写的技巧,尽量多使用&& 和  \ 来区分段,我写的自我感觉是很清晰了,当然有大牛欢迎指正。

以上写出的镜像,我精简到最后未压缩的镜像650M左右,运用到公司业务上使运行速度快了一大截。(因为之前的基础镜像未压缩的时候1G多)

关于run.sh的一些东西,脚本如下:

#!/bin/sh
nginx="/usr/sbin/nginx"
NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"
chown -R www:www /dev/shm/
echo "start nginx..."
$nginx -c $NGINX_CONF_FILE

echo "start php-fpm..."
/etc/init.d/php-fpm start --daemonize
/usr/sbin/rsyslogd

tail -f /dev/null                

这里面就是定义了启动程序如何启动,在docker里面是不支持systemd的,当然可以启用,得在容器启动的时候指定参数,这个官网有讲我就不多说了,在自己写的业务里面就不要想着systemd快速启动的法子了,用脚本指定运行程序和配置,启用即可,重点的是下面的tail -f /dev/null这句,因为docker是不支持后台启动程序的(已经成功启用的docker容器不算),需要在docker启动的时候在前台把程序进程hold住,前台hold住需要用输出和tail -f  /dev/null命令了。

以上就是我写公司业务镜像的经验,希望能帮到大家,也欢迎大牛指正共同学习。

猜你喜欢

转载自www.cnblogs.com/adif0028/p/12157888.html