Build, Ship, and Run Any App, Anywhere.
镜像构建
Dockerfile
# 设置基础镜像为Debian |
构建镜像
- Dockerfile中的每一条指令都会生成一层新的镜像层
- 从一个父镜像开始构建,docker build 的时候会去检查下一条命令的hash值是否于现有镜像层相等,如果相等,则不执行这条命令,而直接基于现有镜像层来执行接下来的语句。
- 对于ADD或者COPY指令来说,docker 会检查每个文件的校验和(元数据和数据),最后修改时间和最后访问时间不作考虑。
- 对于RUN yum install 来说,docker 不会去检查文件的校验和,只检查指令是否变化。如果需要强制更新镜像,那么需要docker build –no-cache
- 一旦从某一层开始不使用cache,接下来的每一层都不会再检查是否有cache
最佳实践
1. FROM
尽可能使用当前官方仓库作为你构建镜像的基础。如果公司内部使用,可下载官方仓库镜像,再推送至私有 registry。推荐使用 Alpine 镜像(Alpine Linux 是一个完整的操作系统),因为其被严格控制并保持在最小尺寸(目前大小 5.52M)。基于此基础镜像,再去构建自己的基础镜像,可以有效控制镜像的大小。
2. LABEL
通过给镜像添加标签可以帮助组织镜像、记录许可信息、辅助自动化构建等。
3. RUN
为了保持 Dockerfile 文件的可读性,可理解性,以及可维护性,过长的或复杂的 RUN 指令使用反斜杠 \ 分行。
RUN yum install -y pip \ |
如果将 RUN apt-get update 和 apt-get install 拆解为两条命令,会导致缓存问题记忆后续的 install 失败。下图从左边修改最后一行再次构建镜像是时,Docker 发现 RUN apt-get update 指令一样。这样会导致 apt-get update 不再执行,使用缓存镜像。后面使用 apt-get install 安装的是过时的 curl 和 nginx 版本。
4. EXPOSE
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P时,会自动随机映射 EXPOSE 的端口。
5. ENV
为容器化服务提供必要的环境变量。
6. ADD 和 COPY
优先使用 COPY,COPY 语义更明确。ADD 能够将本地 tar 文件自动提取到镜像中,这种场景用 ADD 更合适。如果 Dockerfile 中需要 COPY 多个上下文中的文件,不要一次性 COPY 所有文件,这将保证每个步骤的构建缓存只在特定的文件变化时失效。最好的做法是按文件组织结构以及功能去 COPY 文件。
7. VOLUME
建议使用 VOLUME 来管理镜像中的可变部分和用户可以改变的部分,如数据库存储文件、配置文件、容器创建的文件和目录等。
8. WORKDIR
用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行。为了清晰性和可靠性,应该总是在 WORKDIR 中使用绝对路径。
其他
# 使用 .dockerignore |
docker commit
docker commit
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] |
多阶段构建(Docker 17.05 or higher)
# 第一阶段构建生成可执行文件 |
镜像的存储和传输
docker pull
docker push
# docker镜像完整路径 |
docker run 做了什么?
docker 客户端命令行工具 |
Docker Client基础命令总览
Docker仓库相关
docker search |
查看镜像和容器信息
docker ps |
操作容器和镜像
docker run |