基础镜像,接触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命令了。
以上就是我写公司业务镜像的经验,希望能帮到大家,也欢迎大牛指正共同学习。
原文:https://www.cnblogs.com/adif0028/p/12157888.html