Docker 入门到实战教程(五)构建Docker镜像

Docker 镜像(Image)是一种分层结构的文件系统,基于Docker Hub中已构建好的镜像后,我们可以快速构建自己的镜像。还可以将自己构建的镜像免费推送到Docker Hub的用户仓库进行管理,然后就可以基于这些镜像创建容器。

一. 构建准备

1.1 注册账号

构建镜像构建完成后,需要将镜像推送Docker Hub或自已私有Regitry中。本文使用Docker Hub,因此开始前需要首先注册一个Docker Hub帐号。可以在Docker Hub官网https://hub.docker.com完成帐号的注册。

注册时需要输入用户名、邮箱、帐号密码,注册后会收到一封激活邮件,需要登录邮箱完成帐号的激活。

注册后,可以通过docker login命令登录Docker Hub:

docker login
Docker 入门到实战教程(五)构建Docker镜像_第1张图片 file

登录成功后,会收到Login Succeeded提示。登录后们就可以从 docker hub 上拉取自己账号下的全部镜像。认证信息上会被保存(保存于$HOME/.docker/config.json文件),以便之后使用。退出登录可以使用docker logout命令。

docker logout
file

docker commit可以通过修改容器创建新的镜像。这点类似于git commit的提交代码更新,我们可以首先创建一个容器,然后对容器进行修改,修改完成后像提交代码一样将修改提交为一个新镜像。

docker commit命令格式如下:

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

主要选项(OPTIONS)如下:

  • -a, --author - {string}, 作者(如:"John Hannibal Smith ")

  • -c, --change - {list}, 使用Dockerfile指令来创建镜像(默认 [])

  • -m, --message - {string}, 提交备注信息

  • -p, --pause - {string}, 提交时暂停容器(默认 true)

2.1 创建容器

首先创建一个容器,创建容器的镜像依然使用之前使用的centos镜像:

docker run -it --name centos_test my_centos:1.0 /bin/bash
file
2.1.1 安装软件

我们会将这个容器做为一个Web服务器使用,所以需要安装nginxapache

运行容器后,在容器中安装nginx

yum update
yum install nginx
Docker 入门到实战教程(五)构建Docker镜像_第2张图片 file Docker 入门到实战教程(五)构建Docker镜像_第3张图片 file

安装完成后,可以将当前状态保存下来,这样就不用每次都创建容器并重新安装软件了。docker commit提交前,先退出容器:

exit

2.2 提交更改

提交时要通过容器名或容器ID指定所要提交的容器,并要指定一个目标仓库和镜像名。docker commit提交时比较轻量,只会提交创建容器的镜像与容器当前状态之间有差异的部分。

如,提要刚才配置的容器centos_test,并指定目标仓库和镜像名为centos/nginx:

docker commit centos_test centos/nginx
file

提交后,就可以通过docker images命令看到新创建的容器:

docker images centos/nginx
file

提交镜像时,还可以指定一些提交参数和标签等。如:

docker commit -m "一个自定义centos容器" -a "小东啊" centos_test centos/nginx:webserver
file

在这条命令中,我们通过-m参数添加了一些提交备注,通过-a参数添加了镜像作者,并为新镜像添加了webserver标签。

2.2.1 查看镜像:

docker images centos/nginx
file

每次提交都会创建一个新镜像,在centos/nginx仓库下现在有两个不同ID的镜像。现在使用docker inspect命令查看新创建镜像的详细信息:

 docker inspect centos/nginx:webserver
Docker 入门到实战教程(五)构建Docker镜像_第4张图片 file

2.3 使用新镜像

镜像提交会,就可以通过使用提交的镜像来创建容器。

docker run -it centos/nginx:webserver /bin/bash
file

三. 使用Dockerfile构建镜像

使用Dockerfiledocker build命令来构建镜像操作更灵活、过程可重复,因此也更推荐使用这种方式来构建镜像。

Dockerfile基于DSL(Domain Specific Language)语言构建Docker镜像,Dockerfile编写完成后,就可以使用docker build命令来构建一个新镜像。

Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像。
Dockerfile由一行行命令语句组成,并支持以#开头的注释行。
一般而言,Dockerfile分为四部分:基础镜像信息维护者信息镜像操作指令容器启动时执行的命令

3.1 Dockerfile指令说明:

Docker 入门到实战教程(五)构建Docker镜像_第5张图片 file

下面是指令详情:

3.1.1 FROM

说明:指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像。格式:

  FROM 
  FROM :
  FROM @

任何Dockerfile中的第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创造多个镜像,可以使用多个FROM指令,每个镜像一个。

3.1.2 MAINTAINER

说明:指定维护者信息 格式:

  MAINTAINER 

该信息会写入生成镜像的Author属性域中。

3.1.3 RUN

说明:运行指定命令 格式:

  RUN 
  RUN ["executable","param1","param2"]

(RUN ["可执行文本","参数1","参数2"]) 指令会被解析为Json数组,因此必须用双引号。实例:

  RUN echo hello
  RUN ["/bin/bash","-c","echo hello"]

RUN默认会在shell终端中运行命令,即/bin/sh -c
RUN ["","",""]   使用exec执行,不会启动shell环境 每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。
当命令较长时,可以使用\来换行。

3.1.4 CMD

说明:指定启动容器时默认执行的命令。格式:

  CMD ["executable","param1","param2"]使用exec执行,推荐使用的方式
  CMD command param1 param2 在/bin/sh中执行,提供给需要交互的应用
  CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数

每个Dockerfile只能有一条CMD命令,如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时,手动指定了运行的命令(作为run的参数),则会覆盖掉CMD指定的命令。

3.1.5 LABEL

说明:用来指定生成镜像的元数据标签信息。格式:

  LABEL = = =...

实例:

  LABEL version="1.0"
  LABEL description="This is test_label"
3.1.6 EXPOSE

说明:声明镜像内服务所监听的端口 格式:

  EXPOSE  [  ...]

实例:

  EXPORT 22 80 443

注意,该指令只是起到声明作用,并不会自动完成端口映射。如果你要完成映射还是要在创建的时候使用-p/-P参数。

3.1.7 ENV

说明:指定环境变量,在镜像的生成过程中会被后续RUN指令调用,在启动的容器中也会存在。格式:

  ENV  
  ENV =

实例:

  ENV PG_MAJOR 9.8.3

指令指定的环境变量在运行时可以被覆盖。

3.1.8 ADD

说明:复制指定的路径下的内容到容器中的路径下。格式:

  ADD  

实例:

  ADD *.c /code/

其中可以是Dockerfile所在目录的一个相对路径(文件或目录),也可以是一个URL, 还可以是一个tar文件(如果是tar文件会自动解压到路径下)。可以是镜像内的绝对路径,或者相对于工作目录(WORKDIR)的相对路径。

3.1.9 COPY

说明:复制本地主机的(Dockerfile所在目录的相对路径、文件或目录)下的内容到镜像中的下,目标路径不存在时,会自动创建。格式:

  COPY  

当使用本地目录为源目录时,推荐使用COPY

3.1.10 ENTRYPOINT

说明:指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所以传入值作为该命令的参数。格式:

  ENTRYPOINT ["executable","param1","param2"] exec调用执行
  ENTRYPOINT command param1 param2 shell中执行

此时,CMD指令指定值将作为根命令的参数。每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个有效。在运行时,可以被 --entrypoint参数覆盖掉。

3.1.11 VOLUME

说明:创建一个数据卷挂载点。格式:

VOLUME ["/data"]

可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等

3.1.12 USER

说明:指定运行容器时的用户名或UID,后续的RUN等指令也会使用指定的用户身份。格式:

  USER daemon

当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在之前创建所需要的用户。RUN groupadd -r postgres && useradd -r -g postgress postgress 要零时获取管理员权限可以使用gosu或sudo

3.1.13 WORKDIR

说明:为后续的RUN、CMD和ENTRYPOINT指定配置的工作目录。格式:

  WORKDIR /path/to/workdir

可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。

  WORKDIR /a
  WORKDIR b
  WORKDIR c

则最终路径为/a/b/c

3.1.14 ARG

说明:指定一些镜像内使用的参数(例如版本号信息),这些参数在执行docker build命令时才以--build-arg=格式传入。格式:

  ARG  [=]
3.1.15 ONBUILD

说明:配置当前所创建的镜像作为其它镜像的基础镜像时,所执行的创建操作指令。格式:

  ONBUILD [INSTRUCTION]

例如,Dockerfile使用如下类容创建的镜像image-A

    [...]    
ONBUILD ADD . /app/src
    [...]

如果基于镜像image-A创建新的镜像,那么新的镜像就会自动执行上面的ONBUILD指定的内容,类似于继承的关系。

3.1.16 STOPSIGNAL

说明:指定所创建镜像启动的容器接收退出的信号值。实例:

  STOPSIGNAL signal
3.1.17 HEALTHCHECK

说明:配置所启动容器如何进行健康检查(如何判断健康与否) 格式:

  HEALTHCHECK [OPTIONS] CMD command

根据所执行命令返回值是否为0来判断 OPTION支持的选项:  --interval=DURATION(默认为:30s) 过多久检查一次
  --timeout=DURAION(默认为:30s) 每次检查等待结果的超时
  --retries=N(默认为:3) 如果失败了,重试几次才最终确定失败

HEALTHCHECK NONE 禁止基础镜像中的健康检查

3.1.18 SHELL

说明:指定其它命令使用shell时的默认shell类型。实例:

  SHELL ["executable","parameters"]

默认值为 ["/bin/sh","-c"]

3.1 创建Dockerfile文件

首先创建一个目录用于初始化Dockerfile文件

mkdir test_web_server
cd test_web_server
touch Dockerfile
Docker 入门到实战教程(五)构建Docker镜像_第6张图片 file

如上所示,我们使用命令创建test_web_server目录,并在其中创见了Dockerfile文件。这个目录就是我们的构建环境,在Docker中,将这个环境称为上下文(content)或者构建上下文(build content)。构建镜像时,Docker会将构建环境中的文件和目录传递给守护进程,这样守护进程就访问到用户想在镜像中存储的任何代码、文件或其它数据。

接下来,编辑刚创建Dockerfile文件,比如编写Web服务器的构建代码:

# Version: 1.0
FROM centos
MAINTAINER 小东啊 "[email protected]"
RUN yum update -y
RUN yum install -y nginx
RUN echo "Hello World, 我是个web容器" \ 
   > /usr/share/nginx/html/index.html
EXPOSE 80
Docker 入门到实战教程(五)构建Docker镜像_第7张图片 file

在以上示例中,我们首先通过FROM指定了一个基础镜像centos。在Dockerfile中,FROM命令只能有一个,该命令用于指定基础镜像,后续的命令都会基于该镜像进行。接着通过MAINTAINER命令告诉Docker镜像的作者、联系邮箱。

接下来,通过三条RUN语句安装软件环境。在这个示例中,首先通过RUN更新了yum源,然后安装了nginx,最后创建一个文件/usr/share/nginx/html/index.html并在其中添加了一些简单的示例文本。

RUN语句表示要在镜像中运行的命令。默认情况下,RUN指令会在/bin/sh -c。如果不想使用shell执行,可以exec来运行RUN命令,这时需要使用数组来传递指令和参数。如:

RUN ["yum", "install", "-y", "nginx"]

Dockerfile文件的最后,通过EXPOSE命令对外开放了80端口。出于安全考虑,Docker默认不会打开任何端口。EXPOSE会告诉Docker容器内应用将要使用的端口(可以指定多个),但这并不意味着会自动打开该端口,还需要在docker run运行容器时,通过--expose参数来指定要打开的端口。

注意:Dockerfile支持使用注释,注释以#开头,如上例中的第一行。

构建镜像时,构建目录下的文件默认都会被传入守护进程,如果有不需要传递守护进程的文件。可以通过.dockerignore文件指定,该文件类似.gitignore文件,如果创建后会对每行进行模式匹配并排除符合条件的文件。

3.2 关于Dockerfile文件

Dockerfile是由一系列命令和参数组成的一个文件。其中,每条件命令都要大写(如:FROM),且其后都要跟一个参数(如:centos)。构建镜像时,Dockerfile中的命令会按顺序从上到下执行,在编写Dockerfile文件时应注意各条命令的顺序安排。Dockerfile文件中的每条命令,都会创建一个新的镜像层并会提交镜像。

Docker使用Dockerfile构建镜像流程大致如下:

  • 从基础镜像运行一个容器

  • 执行一条命令,对容器进行修改

  • 执行类似docker commit操作,提交一个新的镜像层

  • 基于刚创建的镜像运行一个新容器

  • 继续执行下一条命令,直到所有命令执行完

3.3 docker build构建新镜像

Dockerfile文件创建完成后,就可以通过docker build命令来构建新镜像。执行docker build命令时,Dockerfile中的命令都会被执行和提交,且每次提交都会创建一个新镜像。

开始构建上面的例子,构建过程如下

[root@izuf6f2iqt161crtd1qaapz test_web_server]# docker build -t web_test .
Sending build context to Docker daemon  2.048kB
Step 1/6 : FROM centos
 ---> 470671670cac
Step 2/6 : MAINTAINER 小东啊 "[email protected]"
 ---> Running in 423e78f29e83
Removing intermediate container 423e78f29e83
 ---> 7151b8cda488
Step 3/6 : RUN yum update -y
 ---> Running in f22ddcccc345
CentOS-8 - AppStream                            1.7 MB/s | 6.5 MB     00:03    
CentOS-8 - Base                                 5.4 MB/s | 5.0 MB     00:00    
CentOS-8 - Extras                               2.4 kB/s | 2.1 kB     00:00


Step 4/6 : RUN yum install -y nginx
 ---> Running in 8d288e80e915


Complete!
Removing intermediate container 8d288e80e915
 ---> a0743512819d
Step 5/6 : RUN echo "Hello World, 我是个web容器"    > /usr/share/nginx/html/index.html
 ---> Running in 85e09cec1ad5
Removing intermediate container 85e09cec1ad5
 ---> 753663cf801b
Step 6/6 : EXPOSE 80
 ---> Running in 2bcd8298c48b
Removing intermediate container 2bcd8298c48b
 ---> 8bf8ce5253df
Successfully built 8bf8ce5253df
Successfully tagged web_test:latest


在使用docker build构建镜像时,我们通过-t参数指定web_test做为镜像名

构建镜像时,还可以为镜像设置标签,设置格式为镜像名:标签。如:

docker build -t web_test:v1.0 .

还可以为镜像设置仓库,设置格式为仓库名/镜像名

docker build -t web/web_test:v1.0 .

在构建时我们可以看到,构建上下文被传给了Docker的守护进程。在构建过程中,每执行一条命令都会有一次镜像创建提交,和使用上一步生成的镜像运行新容器的过程。如:

Sending build context to Docker daemon  2.048kB
Step 1/6 : FROM centos


Step 2/6 : MAINTAINER 小东啊 "[email protected]"
 ---> Running in 423e78f29e83
Removing intermediate container 423e78f29e83


Step 6/6 : EXPOSE 80
 ---> Running in 2bcd8298c48b
Removing intermediate container 2bcd8298c48b
 ---> 8bf8ce5253df

在命令的最后,通过.(同./)告诉Docker从本地当前工作目录查找Dockerfile文件

3.3.1 构建缓存

由于构建过程中的每一步都会将结果提交为镜像,Docker 会将这些镜像做为缓存使用。重新构建时,Docker会对比每一步生成的镜像,如果没有变化就不会重新生成镜像,以节约构建时间。如,前面构建出错的情况,重新构建时,Docker并不是从头开始执行,而是直接从上次出错的位置开始。

如果不希望使用缓存,可以为docker build命令指定--no-cache参数。如:

docker build --no-cache -t web_test :v1.0 .

3.4 使用新镜像

使用docker images命令查看刚构建的镜像。

docker images web_test
file

如果想查看镜像的构建过程,可以使用docker history命令查看:

docker history web_test
Docker 入门到实战教程(五)构建Docker镜像_第8张图片 file

通过docker history命令可以查看镜像的每一层,及创建这些层的Dockerfile命令。

3.4.1 使用
docker run -d -P --name web_test web_test
file

四. 新镜像推送到Docker Hub

新镜像构建完成后,可以将其推送到Docker Hub,这样就可以在需要的时候轻松获取和使用镜像,其它人也可以使用你构建的镜像。如果不希望镜像被无关人员看到,可以将其推送到私有仓库。

4.1 登录

docker login

然后输入账号密码

file

4.2 推送镜像

用户登录后,可以通过 docker push 命令将自己的镜像推送到 Docker Hub

如,将前面创建的web_test推送到Docker Hub

 docker push web_test
Docker 入门到实战教程(五)构建Docker镜像_第9张图片 file

如上图所示,我上传镜像失败
发布自己镜像问题denied: requested access to the resource is denied

4.3 denied解决办法:

1.先列出所有镜像

docker images
  1. 将要发布的镜像改到自己账户名下。我的账户名:xiaodonga

docker tag web_test xiaodonga/web
  1. 查看镜像列表

docker images
file

发现自己的已经在自己账户下的

  1. 再次发布镜像

docker push xiaodonga/web

可以在Docker Hub看到上传的镜像,如下图:

Docker 入门到实战教程(五)构建Docker镜像_第10张图片 file

注意:推送镜像时,一定要使用用户ID/仓库名的形式。如果仅使用仓库名,Docker会认为这是一个root仓库,会推送失败。

从上面的推送过程可以看出,镜像是一种分层结构的文件系统。镜像推送到镜像仓库时,这些层都会被推送到仓库中。使用docker rmi删除镜像时,这些层也都会被删除。

参考链接:
http://suo.im/5Nl8gJ
http://suo.im/6obOIe

 往期推荐 

????

Docker 入门到实战教程(一)介绍Docker

Docker 入门到实战教程(二)安装Docker

Docker入门到实战教程(三)镜像和容器

Docker 入门到实战教程(四)容器链接

你可能感兴趣的:(Docker 入门到实战教程(五)构建Docker镜像)