docker构建镜像

某些情况下我们不得不自己构建镜像,比如:

  • 找不到现成的镜像,比如自己开发的应用程序。
  • 需要在镜像中加入特定的功能,比如官方镜像几乎都不提供 ssh。

Docker 提供了两种构建镜像的方法:

  • docker commit 命令
  • Dockerfile 构建文件

一.docker commit

Docker 并不建议用户通过这种方式构建镜像,这是一种手工创建镜像的方式,容易出错,效率低且可重复性弱,
更重要的:使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计,存在安全隐患。
1.步骤
docker commit 命令是创建新镜像最直观的方法,其过程包含三个步骤:

  1. 运行容器
  2. 修改容器
  3. 将容器保存为新的镜像

2.示例

# 启动容器,-it 参数的作用是以交互模式进入容器,并打开终端
[root@VM_0_46_centos ~] docker run -it centos
[root@31b880ff4333 /]

# 安装vim
[root@31b880ff4333 /] vim test.sh
bash: vim: command not found
[root@31b880ff4333 /] yum install -y vim

# 在新窗口中查看当前运行的容器,silly_blackburn 是 Docker 为我们的容器随机分配的名字
[root@VM_0_46_centos ~] docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED              STATUS              PORTS                  NAMES
31b880ff4333        centos              "/bin/bash"          About a minute ago   Up About a minute                          silly_blackburn
170cb8aae061        httpd               "httpd-foreground"   27 hours ago         Up 27 hours         0.0.0.0:8000->80/tcp   wonderful_grothendieck

# 执行 docker commit 命令将容器保存为镜像
[root@VM_0_46_centos ~] docker commit silly_blackburn centos_with_vim
sha256:7b329b86dc1af27a67839d9658a8683b1d199d2d7af6452cb3eb0b6715094e7c

# 查看镜像,centos_with_vim镜像稍大一些
[root@VM_0_46_centos ~] docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos_with_vim     latest              7b329b86dc1a        4 seconds ago       286MB
centos              latest              0f3e07c0138f        2 months ago        220MB

二.Dockerfile

用 Dockerfile(推荐方法)构建镜像,底层也是 docker commit 一层一层构建新镜像的。学习 docker commit 能够帮助我们更加深入地理解构建过程和镜像的分层结构。
1.命令

# 创建文件
vim Dockerfile
FROM centos
RUN yum install -y vim

# 运行 docker build 命令构建镜像
# -t 给新镜像命名:centos-with-vim-dockerfile
# 末尾的 . 指明 build context 为当前目录。Docker 默认会从 build context 中查找 Dockerfile 文件
# 也可以通过 -f 参数指定 Dockerfile 的位置。
[root@VM_0_46_centos mydocker] docker build -t centos-with-vim-dockerfile .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 0f3e07c0138f
Step 2/2 : RUN yum install -y vim
 ---> Running in 46688ed52460
······

2.制作过程
首先 Docker 将 build context 中的所有文件发送给 Docker daemon。
build context 为镜像构建提供所需要的文件或目录。

Dockerfile 中的 ADD、COPY 等命令可以将 build context 中的文件添加到镜像。此例中,build context 为当前目录 ,该目录下的所有文件和子目录都会被发送给 Docker daemon。

执行 FROM,将 centos 作为 base 镜像
执行 RUN,安装 vim
启动临时容器,在容器中通过yum安装 vim
安装成功后,将容器保存为镜像,这一步底层使用的是类似 docker commit 的命令。
删除临时容器

# 查看镜像的构建历史,docker history展示了镜像的分层结构,每一层由上至下排列。
[root@VM_0_46_centos mydocker] docker history centos-with-vim-dockerfile
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
670bd82d6cae        15 minutes ago      /bin/sh -c yum install -y vim                   66.8MB              
0f3e07c0138f        2 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           2 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           2 months ago        /bin/sh -c #(nop) ADD file:d6fdacc1972df524a…   220MB  

Docker 会缓存已有镜像的镜像层,构建新镜像时,如果某镜像层已经存在,就直接使用,无需重新创建。

总结:Dockerfile 构建镜像的过程

  • 从 base 镜像运行一个容器。
  • 执行一条指令,对容器做修改。
  • 执行类似 docker commit 的操作,生成一个新的镜像层。
  • Docker 再基于刚刚提交的镜像运行一个新容器。
  • 重复 2-4 步,直到 Dockerfile 中的所有指令执行完毕。

3.Dockerfile 中最常用的指令

基础镜像的选择 (FROM)

  • 官方镜像优于非官方的镜像,如果没有官方镜像,则尽量选择Dockerfile开源的
  • 固定版本tag而不是每次都使用latest
  • 尽量选择体积小的镜像

RUN
主要用于在Image里执行指令,比如安装软件,下载文件等。
每一行的RUN命令都会产生一层image layer, 导致镜像臃肿,尽量将命令都在一个RUN中执行

文件复制和拷贝
COPYADD 都可以把local的一个文件复制到镜像里,如果目标目录不存在,则会自动创建
ADD 比 COPY高级一点的地方就是,如果复制的是一个gzip等压缩文件时,ADD会帮助我们自动去解压缩文件。

FROM python:3.9.5-alpine3.13
COPY hello.py /app/hello.py

FROM python:3.9.5-alpine3.13
ADD hello.tar.gz /app/

构建参数和环境变量 (ARG vs ENV)
ARG仅在镜像构建时生效
ENV设置的变量还可以在Image中保持,作为容器中的环境变量

FROM ubuntu:20.04
ENV VERSION=2.0.1
RUN apt-get update && \
    apt-get install -y wget && \
    wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \
    tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \
    mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \
    rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz

ARG参数可以通过 --build-arg 动态修改对应的value

docker image build -f .\Dockerfile-arg -t ipinfo-arg-2.0.0 --build-arg VERSION=2.0.0 .
容器启动命令 CMD

CMD可以用来设置容器启动时默认会执行的命令。

  • 容器启动时默认执行的命令
  • 如果docker container run启动容器时指定了其它命令,则CMD命令会被替代
  • 如果定义了多个CMD,只有最后一个会被执行。
容器启动命令 ENTRYPOINT

ENTRYPOINT 也可以设置容器启动时要执行的命令,但是和CMD是有区别的。

  • CMD 设置的命令,可以在docker container run 时传入其它命令,覆盖掉 CMD 的命令,但是 ENTRYPOINT 所设置的命令是一定会被执行的。
  • ENTRYPOINTCMD 可以联合使用,ENTRYPOINT 设置执行的命令,CMD传递参数
  • CMD 或 docker run 之后的参数会被当做额外的参数传递给 ENTRYPOINT。
FROM ubuntu:20.04
ENTRYPOINT ["echo", "hello docker"]

$ docker container run -it --rm demo-entrypoint
hello docker
# echo "hello world" 被整体当成参数传递给ENTRYPOINT
$ docker container run -it --rm demo-entrypoint echo "hello world"
hello docker echo hello world

WORKDIR
为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录,目录不存在时会自动创建

EXPOSE
指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来。

VOLUME
将文件或目录声明为 volume

MAINTAINER
设置镜像的作者,可以是任意字符串。

使用技巧
  • 合理使用缓存:对可能会变化的命令往后放
  • .dockerignore:Docker是client-server架构,在构建docker镜像的时候,需要把所需要的文件由CLI(client)发给Server,这些文件实际上就是build context
  • 不要在构建阶段做编译,编译时有大量依赖会增加镜像体积

dockerhub上官方镜像使用的DockerFile:https://github.com/docker-library/official-images

三.镜像的命名

一个特定镜像的名字由两部分组成:repository 和 tag。
如果执行 docker build 时没有指定 tag,会使用默认值 latest
tag 常用于描述镜像的版本信息

参考:《每天5分钟玩转Docker容器技术》
https://item.jd.com/16936307278.html
https://dockertips.readthedocs.io/en/latest/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Docker 构建镜像是通过编写 Dockerfile 文件来指定构建镜像的步骤和配置。Dockerfile 是由多条指令构成的,每一条指令对应于 Docker 镜像中的每一层。Dockerfile 中的每个指令都会创建一个镜像层,这个层可以理解为一个临时的容器。每个指令都会在当前的层上进行操作,执行完后,当前层的状态将被记录下来并成为下一层的基础。这样就实现了镜像分层的原理。 在构建 Docker 镜像时,可以根据需要使用不同的指令,例如使用 FROM 指令选择基础镜像,使用 RUN 指令执行命令,使用 COPY 指令复制文件,使用 EXPOSE 指令暴露端口等等。通过这些指令的组合,可以按照需求来构建具有特定功能和配置的镜像。 举例来说,可以通过编写 Dockerfile 来构建一个包含 SSH 服务的镜像。在 Dockerfile 中,可以使用基础镜像、安装 SSH 服务的指令来构建,最后可以通过构建镜像来运行 SSH 服务。同样的原理也适用于构建其他类型的镜像,例如包含 Systemctl 或 Tomcat 的镜像。 总结来说,Docker 构建镜像是通过编写 Dockerfile 文件,使用多条指令来指定构建镜像的步骤和配置。每个指令都会创建一个镜像层,实现了镜像分层的原理。可以根据需求选择不同的指令来构建具有特定功能和配置的镜像。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Dockerfile构建镜像](https://blog.csdn.net/gcc001224/article/details/125864815)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值