就前面两篇文章Docker 容器化部署实践--入门,Docker容器化部署实践Docker Compose,我讲了Docker常用命令的使用,通过docker-compose.yml文件进行Docker容器化的编排。
这其中我们基本都是直接Docker pull进行镜像拉取的。我们如果是使用一些基础组件,直接拉取官方当然是很方便,比如nginx,redis,mongo等等。
但是我们应用服务基本会做一些构建操作,做一些定制化操作,安装一些我们需要的特定包。所以今天我们来聊一下Docker的镜像制作,使用Dockerfile进行镜像的构建。
一个例子
为了更好的理解,我们这儿以 hub.docker.com
的官方redis进行为例进行讲解。注释请看命令后面。
FROM debian:stretch-slim # 基于debian进行安装 RUN groupadd -r redis && useradd -r -g redis redis # 执行命令,创建用户组 ENV GOSU_VERSION 1.10 # 设置环境变量 gosu 类sudo工具 RUN set -ex; \ \ fetchDeps=" \ ca-certificates \ dirmngr \ gnupg \ wget \ "; \ apt-get update; \ apt-get install -y --no-install-recommends $fetchDeps; \ # 省略部分命令 ENV REDIS_VERSION 5.0.1 ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-5.0.1.tar.gz ENV REDIS_DOWNLOAD_SHA 82a67c0eec97f9ad379384c30ec391b269e17a3e4596393c808f02db7595abcb # for redis-sentinel see: http://redis.io/topics/sentinel RUN set -ex; \ \ buildDeps=' \ ca-certificates \ wget \ \ gcc \ libc6-dev \ make \ '; \ apt-get update; \ apt-get install -y $buildDeps --no-install-recommends; \ # 省略部分命令 RUN mkdir /data && chown redis:redis /data VOLUME /data # 挂载匿名卷,避免容器存储层会发生写操作。 WORKDIR /data # 指定工作路径避免 RUN cd .. && do things COPY docker-entrypoint.sh /usr/local/bin/ # 复制源文件sh到目标bin目录,文件权限保持不变 ENTRYPOINT ["docker-entrypoint.sh"] # 配置容器启动时运行的命令 EXPOSE 6379 # 声明需要监听的端口 CMD ["redis-server"] # 设置镜像的启动命令
ENTRYPOINT和CMD的区别是:其中ENTRYPOINT
是提供镜像的主命令,允许将镜像当成命令本身来运行,这里是结合辅助脚本docker-entrypoint.sh 使用,CMD
提供命令默认选项。docker-entrypoint.sh 文件和Dockerfile目录一个层级,下面是docker-entrypoint.sh 文件。
# docker-entrypoint.sh #!/bin/sh set -e # first arg is `-f` or `--some-option` # or first arg is `something.conf` if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then set -- redis-server "$@" fi # allow the container to be started with `--user` if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then find . \! -user redis -exec chown redis '{}' + exec gosu redis "$0" "$@" fi exec "$@"
如果我们要加入自己的配置文件,可以在基于官方redis添加Dockerfile和对应的redis.conf文件。
# Dockerfile FROM redis COPY redis.conf /usr/local/etc/redis/redis.conf CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ] # 后面配置文件是命令对应的参数。
上面的Dockerfile文件声明了镜像的基础镜像,记录着镜像的步骤命令,编写好上面的Dockerfile文件之后,我们使用docker build 命令就可以生成新镜像。
打包镜像要注意
- 精简镜像:尽量让每个镜像的用途都比较集中、单一;
- 避免不必要的包,比如编辑器
- 推荐使用 alpine 只有5MB 或者 debian等小巧镜像。
- 使用明确的版本号信息,而非latest,避免一些意外情况。
- 减少镜像层数,尽量合并指令,例如多个RUN指令可以合并为一条;
- 提高构建镜像速度,在目录下新建一个 .dockerignore 文件来指定要忽略的文件和目录同.gitignore.
另外如果我们没有使用自己构建的镜像,一定要注意第三方镜像的安全性,尽可能从官方维护拉取。因为Docker通过命名空间进行隔离,容器中的应用可以访问系统内核和部分系统文件。如果容器中应用是不可信的,会影响到本地系统。
最后官方提供了编写Dockerfile的最佳实践,感兴趣的同学强烈建议你点击原文进行查看。今天我们就分享到这儿,有问题欢迎交流。
容器化部署实践,我打算从基础操作到实战应用以一个系列进行分享,今天是第三篇Dockerfile 镜像构建,后期我将持续分享更多相关内容,从容器化入门使用到部署实践编排构建等等,欢迎大家持续进行关注。