镜像构建介绍
在什么情况下我们需要自己构建镜像那?
(1) 当我们找不到现有的镜像, 比如自己开发的应用程序
(2) 需要在镜像中加入特定的功能
docker 构建镜像有两种方式: docker commit 命令与 Dockerfile 构建文件
docker commit 构建镜像
dockercommit 构建进行主要有三步:
运行容器
修改容器
将容器保存为新的镜像
比如在 CentOS 镜像中安装 VIM 编辑器并存为新的镜像
(1) 运行容器
- [[email protected] docker]# docker run -it CentOS
- Unable to find image 'centos:latest' locally
- latest: Pulling from library/CentOS
- a02a4930cb5d: Pull complete
- Digest: sha256:184e5f35598e333bfa7de10d8fb1cebb5ee4df5bc0f970bf2b1e7c7345136426
- Status: Downloaded newer image for CentOS:latest
(2) 安装 VIM 编辑器
VIM 编辑器确认没有安装
- [[email protected] /]# VIM
- bash: VIM: command not found
进行安装
[[email protected] /]# yum install VIM -y
(3) 保存为新得镜像
首先查看当前运行的镜像
- [[email protected] ~]# docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 69f501e858a6 CentOS "/bin/bash" 2 minutes ago Up 2 minutes quizzical_torvalds
使用 commit 存为新的镜像
- [[email protected] ~]# docker commit 69f501e858a6 CentOS-VIM
- sha256:42083b89a179368bc29a8f40d14f8824990183c8e4b28fd84411d440c26342e5
69f501e858a6 是运行容器的 ID 使用 name 下面的名称也行
CentOS-VIM 是新镜像的名字
查看一下是否有了 CentOS-VIM 镜像
重新启动新的镜像, 验证是否可以使用 VIM 编辑器
可以发现新的镜像可以使用 VIM 编辑器了
- [[email protected] ~]# docker run -it CentOS-VIM
- [[email protected] /]# VIM
- [[email protected] /]# VIM test
上面演示了如何使用 commit 创建新的镜像, 但是 docker 并不建议使用这种方式创建镜像, 原因如下:
这是一种手工创建镜像的方式, 容器出错, 而且效率低且可重复性弱
更重要的是. 使用者并不知道镜像是如何创建出来的. 里面是否有恶意程序
Dockerfile 构建镜像
第一个 Dockerfike
第一步: 创建一个新的目录
[[email protected] ~]# mkdir /test
第二步: 编写 Dockerfile
名称就叫 Dockerfile, 且第一个 D 需要大写
- [[email protected] ~]# cat Dockerfile
- FROM CentOS
- RUN yum install VIM -y
FROMcentos 表示使用 CentOS 这个基础镜像
RUN 表示在 CentOS 上安装 VIM 编辑器
第三步: 构建镜像
[[email protected] ~]# docker build -t CentOS-vim2 .
-t 后面指定新的镜像的标签名 (tag)
. 最后的一个点指明 docker context 为当前目录. docker 默认会从 build context 中查找 Dockerfile 文件, 我们也可以通过 - f 参数指定 Dockerfile 的位置
第四步: 查看镜像
查看镜像分层结构
docker history 会显示镜像的构建历史, 也就是 Dockerfile 的执行过程.
Dcokerfile 常用指令
1.FROM
指定 base 镜像
2. MAINTAINER
设置镜像的作者. 可以是任意的字符
3.COPY
将文件从 build context 复制到镜像
COPY 支持两种格式: COPY src dest 和 COPY ["src","dest"]
注意: src 只能制动 build context 中的文件或目录即在和 Dockerfile 同目录下才可以
4.ADD
与 COPY 类似, 从 build context 复制文件到镜像.
不同的是, 如果 src 是归档文件 (tar,zip,tgz,xz), 文件会被自动接要到 dest
5.ENV
设置环境变量, 环境变量可被后面的指令使用, 例如:
- ENV name ken RUN echo $name
- 6.EXPOSE
指定容器中的进程会监听某个端口, Docker 可以将该端口暴露出来
7.VOLUME
将文件或目录声明为 volume
8.WORKDIR
为后面的 RUN,ENTRYPINT,ADD,COPY 指令设置镜像中的当前工作目录
9.RUN
在容器中运行指定的命令
10.CMD
容器启动时运行指定的命令
dockerfile 中可以多个 CMD 指令, 但是只要最后一个生效. CMD 可以被 docker run 之后的参数替换
11.ENTRYPOINT
设置容器启东市的命令
dockerfile 中可以有多个 ENTRYPOINT, 但是只有最后一个生效.
CMD 或者 docker run 之后的参数会被当做参数传递给 ENTERYPOINT.
Dockerfile 演示
下面演示一个比较全面的 dockerfile
- [[email protected] test]# cat Dockerfile
- #my Dockerfile
- FROM busybox
- MAINTAINER ken
- WORKDIR /ken
- RUN touch test
- COPY ["ken1","."]
- ADD ["wordpress.tar.gz","."]
- ENV name "ken"
注意: Dockerfile 支持以 #开头的注释
构建镜像
- [[email protected] test]# docker build -t myimage .
- Sending build context to Docker daemon 4.281MB
- Step 1/7 : FROM busybox
- ---> 3a093384ac30
- Step 2/7 : MAINTAINER ken
- ---> Running in 2a73a83507ce
- Removing intermediate container 2a73a83507ce
- ---> 8c3df9b3d823
- Step 3/7 : WORKDIR /ken
- ---> Running in 31c6f9fe2195
- Removing intermediate container 31c6f9fe2195
- ---> a458cf986072
- Step 4/7 : RUN touch test
- ---> Running in e1b08ebd363c
- Removing intermediate container e1b08ebd363c
- ---> 41601920009a
- Step 5/7 : COPY ["ken1","."]
- ---> 2ebfa0933fca
- Step 6/7 : ADD ["wordpress.tar.gz","."]
- ---> d0ad29d3aa34
- Step 7/7 : ENV name "ken"
- ---> Running in fceae6e20e63
- Removing intermediate container fceae6e20e63
- ---> 7efe0600e48f
- Successfully built 7efe0600e48f
- Successfully tagged myimage:latest
查看镜像
运行该镜像
- [[email protected] test]# docker run -it myimage
- /ken # ls
- ken1 test WordPress
- /ken # echo $name
- ken
可以发现当前工作目录为 / ken, 且自动创建
ken1 是我们从 docker context 目录中复制过去的
test 是使用 touch 创建的
wordpres 压缩包已经被自动解压
$name 为变量值为 ken
RUN,CMD,ENTRYPOINT
这三个指令看上去很类似, 很容易混淆, 简单来说:
RUN: 执行命令创建新的镜像层, RUN 经常用于安装软件包
CMD: 设置容器启动后默认执行的命令及参数, 但 CMD 能够被 docker run 后面跟的命令行参数替换
ENTRYPOINT: 配置容器启动时运行的命令
使用 RUN 指令安装应用和软件包, 构建镜像.
如果 Docker 镜像的用途是运行应用程序或服务, 比如运行一个 MySQL, 应该优先使用 Exec 格式的 ENTRYPOINT 指令. CMD 可为 ENTRYPOINT 提供额外的默认参数, 同时可利用 docker run 命令行替换默认参数.
如果想为容器设置默认的启动命令, 可使用 CMD 指令. 用户可在 docker run 命令行中替换此默认命令.
Shell 和 Exec 格式
可以用两种方式制定 RUN,CMD,ENTRYPOINT 要运行的命令: shell 格式以及 exec 格式
shell 举例:
- RUN echo "hello world"
- CMD echo "hello world"
- ENTRYPOINT echo "hello world"
当指令执行时, shell 格式底层会调用 / bin/sh -c [command]. 例如下面的 dockerfile 片段:
- ENV name ken
- ENTRYPOINT echo "Hello, $name"
执行 docker run <image> 将输出:
Hello, ken
注意环境变量 name 已经被值 ken 替换.
下面来看 Exec 格式.
Exec 格式
<instruction> ["executable", "param1", "param2", ...]
例如:
- RUN ["yum", "install", "python3"]
- CMD ["/bin/echo", "Hello world"]
- ENTRYPOINT ["/bin/echo", "Hello world"]
当指令执行时, 会直接调用 <command>, 不会被 shell 解析.
例如下面的 Dockerfile 片段:
- ENV name ken
- ENTRYPOINT ["/bin/echo", "Hello, $name"]
运行容器将输出:
Hello, $name
注意环境变量 "name" 没有被替换.
如果希望使用环境变量, 照如下修改
- ENV name ken
- ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]
运行容器将输出:
Hello, ken
CMD 和 ENTRYPOINT 推荐使用 Exec 格式, 因为指令可读性更强, 更容易理解. RUN 则两种格式都可以.
来源: http://www.bubuko.com/infodetail-3164328.html