使用Dockerfile构建Docker镜像(3)

5. Dockerfile参考示例

示例1:构建Wordpress + nginx运行环境

# 指定基于的基础镜像 FROM Ubuntu:14.04 # 维护者信息 MAINTAINER Eugene Ware <eugene@noblesamurai.com> # Keep upstart from complaining RUN dpkg-divert --local --rename --add /sbin/initctl RUN ln -sf /bin/true /sbin/initctl # Let the conatiner know that there is no tty ENV DEBIAN_FRONTEND noninteractive RUN apt-get update RUN apt-get -y upgrade # Basic Requirements RUN apt-get -y install MySQL-server mysql-client nginx php5-fpm php5-mysql php-apc pwgen Python-setuptools curl git unzip # Wordpress Requirements RUN apt-get -y install php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-sqlite php5-tidy php5-xmlrpc php5-xsl # mysql config, 配置MySQL运行参数 RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf # nginx config, 配置Nginx运行参数 RUN sed -i -e"s/keepalive_timeout\s*65/keepalive_timeout 2/" /etc/nginx/nginx.conf RUN sed -i -e"s/keepalive_timeout 2/keepalive_timeout 2;\n\tclient_max_body_size 100m/" /etc/nginx/nginx.conf RUN echo "daemon off;" >> /etc/nginx/nginx.conf # php-fpm config RUN sed -i -e "s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g" /etc/php5/fpm/php.ini RUN sed -i -e "s/upload_max_filesize\s*=\s*2M/upload_max_filesize = 100M/g" /etc/php5/fpm/php.ini RUN sed -i -e "s/post_max_size\s*=\s*8M/post_max_size = 100M/g" /etc/php5/fpm/php.ini RUN sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf RUN sed -i -e "s/;catch_workers_output\s*=\s*yes/catch_workers_output = yes/g" /etc/php5/fpm/pool.d/www.conf RUN find /etc/php5/cli/conf.d/ -name "*.ini" -exec sed -i -re 's/^(\s*)#(.*)/\1;\2/g' {} \; # nginx site conf,将本地Nginx配置文件复制到容器中的目录 ADD ./nginx-site.conf /etc/nginx/sites-available/default # Supervisor Config RUN /usr/bin/easy_install supervisor RUN /usr/bin/easy_install supervisor-stdout ADD ./supervisord.conf /etc/supervisord.conf # Install Wordpress ADD https://wordpress.org/latest.tar.gz /usr/share/nginx/latest.tar.gz RUN cd /usr/share/nginx/ && tar xvf latest.tar.gz && rm latest.tar.gz RUN mv /usr/share/nginx/html/5* /usr/share/nginx/wordpress RUN rm -rf /usr/share/nginx/www RUN mv /usr/share/nginx/wordpress /usr/share/nginx/www RUN chown -R www-data:www-data /usr/share/nginx/www # Wordpress Initialization and Startup Script ADD ./start.sh /start.sh RUN chmod 755 /start.sh # private expose EXPOSE 3306 EXPOSE 80 # volume for mysql database and wordpress install VOLUME ["/var/lib/mysql", "/usr/share/nginx/www"] # 容器启动时执行命令 CMD ["/bin/bash", "/start.sh"]

示例2:构建Ruby on Rails环境

# 指定基础镜像 FROM fcat/ubuntu-universe:12.04 # development tools RUN apt-get -qy install git vim tmux # ruby 1.9.3 and build dependencies RUN apt-get -qy install ruby1.9.1 ruby1.9.1-dev build-essential libpq-dev libv8-dev libsqlite3-dev # bundler RUN gem install bundler # create a "rails" user # the Rails application will live in the /rails directory RUN adduser --disabled-password --home=/rails --gecos "" rails # copy the Rails app # we assume we have cloned the "docrails" repository locally # and it is clean; see the "prepare" script ADD docrails/guides/code/getting_started /rails # Make sure we have rights on the rails folder RUN chown rails -R /rails # copy and execute the setup script # this will run bundler, setup the database, etc. ADD scripts/setup /setup RUN su rails -c /setup # copy the start script ADD scripts/start /start EXPOSE 3000 # 创建用户 USER rails # 设置容器启动命令 CMD /start

示例3: 构建Nginx运行环境

# 指定基础镜像 FROM sameersbn/ubuntu:14.04.20161014 # 维护者信息 MAINTAINER sameer@damagehead.com # 设置环境 ENV RTMP_VERSION=1.1.10 NPS_VERSION=1.11.33.4 LIBAV_VERSION=11.8 NGINX_VERSION=1.10.1 NGINX_USER=www-data NGINX_SITECONF_DIR=/etc/nginx/sites-enabled NGINX_LOG_DIR=/var/log/nginx NGINX_TEMP_DIR=/var/lib/nginx NGINX_SETUP_DIR=/var/cache/nginx # 设置构建时变量,镜像建立完成后就失效 ARG BUILD_LIBAV=false ARG WITH_DEBUG=false ARG WITH_PAGESPEED=true ARG WITH_RTMP=true # 复制本地文件到容器目录中 COPY setup/ ${NGINX_SETUP_DIR}/ RUN bash ${NGINX_SETUP_DIR}/install.sh # 复制本地配置文件到容器目录中 COPY nginx.conf /etc/nginx/nginx.conf COPY entrypoint.sh /sbin/entrypoint.sh # 运行指令 RUN chmod 755 /sbin/entrypoint.sh # 允许指定的端口 EXPOSE 80/tcp 443/tcp 1935/tcp # 指定网站目录挂载点 VOLUME ["${NGINX_SITECONF_DIR}"] ENTRYPOINT ["/sbin/entrypoint.sh"] CMD ["/usr/sbin/nginx"]

示例4:构建Postgres镜像

# 指定基础镜像 FROM sameersbn/ubuntu:14.04.20161014 # 维护者信息 MAINTAINER sameer@damagehead.com # 设置环境变量 ENV PG_APP_HOME="/etc/docker-postgresql" PG_VERSION=9.5 PG_USER=postgres PG_HOME=/var/lib/postgresql PG_RUNDIR=/run/postgresql PG_LOGDIR=/var/log/postgresql PG_CERTDIR=/etc/postgresql/certs ENV PG_BINDIR=/usr/lib/postgresql/${PG_VERSION}/bin PG_DATADIR=${PG_HOME}/${PG_VERSION}/main # 下载PostgreSQL RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && echo 'deb trusty-pgdg main' > /etc/apt/sources.list.d/pgdg.list && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y acl postgresql-${PG_VERSION} postgresql-client-${PG_VERSION} postgresql-contrib-${PG_VERSION} && ln -sf ${PG_DATADIR}/postgresql.conf /etc/postgresql/${PG_VERSION}/main/postgresql.conf && ln -sf ${PG_DATADIR}/pg_hba.conf /etc/postgresql/${PG_VERSION}/main/pg_hba.conf && ln -sf ${PG_DATADIR}/pg_ident.conf /etc/postgresql/${PG_VERSION}/main/pg_ident.conf && rm -rf ${PG_HOME} && rm -rf /var/lib/apt/lists/* COPY runtime/ ${PG_APP_HOME}/ COPY entrypoint.sh /sbin/entrypoint.sh RUN chmod 755 /sbin/entrypoint.sh # 指定端口 EXPOSE 5432/tcp # 指定数据挂载点 VOLUME ["${PG_HOME}", "${PG_RUNDIR}"] # 切换目录 WORKDIR ${PG_HOME} # 设置容器启动时执行命令 ENTRYPOINT ["/sbin/entrypoint.sh"]

具体用例可以参考Github的Docker文件相应的示例。

6. Dockerfile最佳实践

使用.dockerignore文件

为了在docker build过程中更快上传和更加高效,应该使用一个.dockerignore文件用来排除构建镜像时不需要的文件或目录。例如,除非.git在构建过程中需要用到,否则你应该将它添加到.dockerignore文件中,这样可以节省很多时间。

避免安装不必要的软件包

为了降低复杂性、依赖性、文件大小以及构建时间,应该避免安装额外的或不必要的包。例如,不需要在一个数据库镜像中安装一个文本编辑器。

每个容器都跑一个进程

在大多数情况下,一个容器应该只单独跑一个程序。解耦应用到多个容器使其更容易横向扩展和重用。如果一个服务依赖另外一个服务,可以参考 Linking Containers Together

最小化层

我们知道每执行一个指令,都会有一次镜像的提交,镜像是分层的结构,对于 Dockerfile,应该找到可读性和最小化层之间的平衡。

多行参数排序

如果可能,通过字母顺序来排序,这样可以避免安装包的重复并且更容易更新列表,另外可读性也会更强,添加一个空行使用 \ 换行:

RUN apt-get update && apt-get install -y bzr cvs git mercurial subversion

创建缓存

镜像构建过程中会按照 Dockerfile 的顺序依次执行,每执行一次指令 Docker 会寻找是否有存在的镜像缓存可复用,如果没有则创建新的镜像。如果不想使用缓存,则可以在docker build 时添加--no-cache=true选项。

从基础镜像开始就已经在缓存中了,下一个指令会对比所有的子镜像寻找是否执行相同的指令,如果没有则缓存失效。在大多数情况下只对比 Dockerfile 指令和子镜像就足够了。ADD 和 COPY 指令除外,执行 ADD 和 COPY 时存放到镜像的文件也是需要检查的,完成一个文件的校验之后再利用这个校验在缓存中查找,如果检测的文件改变则缓存失效。RUN apt-get -y update命令只检查命令是否匹配,如果匹配就不会再执行更新了。

为了有效地利用缓存,你需要保持你的Dockerfile一致,并且尽量在末尾修改。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8522095e87d953bf06000b17b3870f2a.html