开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
Docker定制镜像
当我们从docker镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。 • 1.从已经创建的容器中更新镜像,并且提交这个镜像 • 2.使用 Dockerfile 指令来创建一个新的镜像
Dockerfile 定制镜像
镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写 入一个脚本,用这个脚本来构建、定制镜像, 那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题 就都会解决。这个脚本就是 Dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容, 就是描述该层应当如何构建。
Dockerfile常用命令
FROM --指定基础镜像
基础镜像不存在会在Docker Hub上拉去(一般会是文件的第一个指令)
使用格式:
FROM <镜像>:[tag]
FROM <镜像>@digest[校验码]
当前主机没有此镜像时,会自动去官网HUB下载
MAINTAINER
--提供Dockerfile 制作者提供本人信息
[逐渐废弃] LABLE --替代MAINTANIER 具体使用: LABLE maintainer="作者信息"
使用格式:
MAINTANIER "guoweixin <guoweixin@aliyun.com>"
ENV
ENV指令可以用于为docker容器设置环境变量 ENV设置的环境变量,可以使用 docker inspect命令来查看。同时
还可以使用docker run --env =来修改环境变量。
USER
用来切换运行属主身份的。Docker 默认是使用 root,但若不需要,建议切换使用者身分,毕竟 root 权限太大
了,使用上有安全的风险。
WORKDIR
WORKDIR 用来切换工作目录的。
Docker 默认的工作目录是/,只有 RUN 能执行 cd 命令切换目录,而且还只作用在当下下的 RUN,也就是说每一
个 RUN 都是独立进行的。
如果想让其他指令在指定的目录下执行,就得靠 WORKDIR。WORKDIR 动作的目录改变是持久的,不用每个指
令前都使用一次 WORKDIR。
VOLUME
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
--卷
只能定义docker管理的卷: VOLUME /data/mysql运行的时候会随机在宿主机的目录下生成一个卷目录!
COPY
--把宿主机中的文件复制到镜像中去!
文件要在Dockerfile工作目录 src 原文件 --支持通配符 --通常相对路径 dest 目标路径
--通常绝对路径
举例:
COPY 1.jpg /usr/local/tomcat/webapps/ROOT/
ADD
类似COPY命令
ADD 将文件从路径 复制添加到容器内部路径 。
必须是想对于源文件夹的一个文件或目录,也可以是一个远程的url。
是目标容器中的绝对路径。 所有的新文件和文件夹都会创建UID 和 GID。事实上如果 是一个远程文件URL,那
么目标文件的权限将会是 600 。
EXPOSE
为容器打开指定要监听的端口以实现与外部通信
使用格式: EXPOSE 80/tcp 23/udp
不加协议默认为tcp
使用-P选项可以暴露这里指定的端口! 但是宿主的关联至这个端口的端口是随机的!
RUN
RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。其格式
有两种: • shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 RUN 指令就是 这种格式。
- exec 格式:RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式。
使用格式: RUN RUN ["","",""]
RUN 就像 Shell 脚本一样可以执行命令,那么我们是否就可以像 Shell 脚本一样把每个命令对应一个 RUN 呢?比如这 样:
Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,和刚才我们手工建立镜像的过程一样: 新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。 而上面的这种写法,创建 了 多 层镜像。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软 件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。 这是很多初 学 Docker 的人常犯的一个错误。
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget http://download.redis.io/releases/redis-4.0.1.tar.gz
RUN tar xzf redis-4.0.1.tar.gz
RUN cd redis-4.0.
Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。上面的 Dockerfile 正确的写法应该是这样:
首先,之前所有的命令只有一个目的,就是编译、安装 redis 可执行文件。因此没有必要建立很多层,这只是一层的 事情。因此,这里没有使用很多个 RUN 对一一对应不同的命令,而是仅仅使用一个 RUN 指令,并使用 && 将各个所 需命令串联起来。将之前的 7 层,简化为了 1 层。在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。 并且,这里为了格式化还进行了换行。Dockerfile 支持 Shell 类的行尾添加 \ 的 命令换行方式,以及行首 # 进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障更为容易,这 是一个比较好的习惯。