玩转Docker(三):构建镜像、使用镜像

2023-12-16 17:29:57

使用现成镜像的好处除了省去自己做镜像的工作量外,更重要的是可以利用前人的经验。特别是使用那些官方镜像,因为Docker的工程师知道如何更好地在容器中运行软件。

当然,某些情况下我们也不得不自己构建镜像,比如:(1)找不到现成的镜像,比如自己开发的应用程序。(2)需要在镜像中加入特定的功能,比如官方镜像几乎都不提供ssh。

Docker提供了两种构建镜像的方法: docker commit命令与Dockerfile构建文件。

一、构建镜像——Docker commit

  • 主要包含以下三个步骤:

● 在base镜像基础上运行容器。
● 修改容器。
● 将容器保存为新的镜像。

  • 实例:在Ubuntu base镜像中安装nginx并保存为新镜像。
# 创建一个名为temp-nginx-container的新容器,并使用Ubuntu基础镜像启动一个交互式的bash会话:
# -it: 分配一个伪终端并保持标准输入打开
sudo docker run -it --name temp-nginx-container ubuntu /bin/bash
# 在新创建的容器中,安装Nginx:
# -y: 这是一个选项,表示在安装过程中自动回答 yes,即在提示时自动选择“是”。
apt update
apt install -y nginx
# 安装完成后,可以退出容器的bash会话,并停止该容器:
exit
sudo docker stop temp-nginx-container
# 使用docker commit命令将修改后的容器保存为新的镜像:
# 创建一个名为my-nginx-image的新镜像,其中包含了你在temp-nginx-container容器中所做的修改
sudo docker commit temp-nginx-container my-nginx-image
# 使用以下命令来查看新创建的镜像:
sudo docker images
  • 并不推荐用这种方式创建镜像:

(1)这是一种手工创建镜像的方式,容易出错,效率低且可重复性弱。比如要在debian base镜像中也加入vi,还得重复前面的所有步骤。
(2)更重要的:使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计,存在安全隐患。

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

二、构建镜像——Dockerfile

Dockerfile是一个文本文件,记录了镜像构建的所有步骤。

1.常用指令

  • FROM
    指定base镜像。
  • MAINTAINER
    设置镜像的作者,可以是任意字符串。
  • COPY
    将文件从build context复制到镜像。
    COPY支持两种形式: COPY src dest与COPY [“src”, “dest”]。
    注意:src只能指定build context中的文件或目录。
  • ADD
    与COPY类似,从build context复制文件到镜像。
    不同的是,如果src是归档文件(tar、zip、tgz、xz等),文件会被自动解压到dest。
  • ENV
    设置环境变量,环境变量可被后面的指令使用。
  • EXPOSE
    指定容器中的进程会监听某个端口,Docker可以将该端口暴露出来。
  • VOLUME
    将文件或目录声明为volume。
  • WORKDIR
    为后面的RUN、CMD、ENTRYPOINT、ADD或COPY指令设置镜像中的当前工作目录。
  • RUN
    在容器中运行指定的命令。
  • CMD
    容器启动时运行指定的命令。
    Dockerfile中可以有多个CMD指令,但只有最后一个生效。CMD可以被docker run之后的参数替换。
  • ENTRYPOINT
    设置容器启动时运行的命令。
    Dockerfile中可以有多个ENTRYPOINT指令,但只有最后一个生效。
    CMD或docker run之后的参数会被当作参数传递给ENTRYPOINT。

2.Shell和Exec格式

当谈到Shell和Exec格式时,通常是指在编写脚本或命令时使用的两种不同的语法格式。这两种格式在编写脚本或命令时有着不同的特点和用途。

  1. Shell格式

    • Shell格式通常指的是在脚本中使用的命令行语法,这种语法是由Shell解释器(如Bash、Zsh等)直接执行的。
    • 在Shell格式中,可以使用各种Shell的内置命令、控制结构(如if语句、for循环等)以及Shell的特定语法。
    • 例如,在Bash脚本中,你可以使用if语句来进行条件判断,使用for循环来进行迭代操作,以及使用各种Shell内置命令来完成特定的任务。
  2. Exec格式

    • Exec格式通常指的是在编写可执行程序或在命令行中直接执行的命令时使用的语法格式。
    • 在Exec格式中,命令的参数和选项通常是按照特定的语法规则来组织的,这种语法规则通常由具体的命令或程序所定义。
    • 例如,对于ls命令,你可以使用ls -l来列出详细信息,这里的-l就是ls命令的选项之一,遵循了ls命令的Exec格式。

总的来说,Shell格式主要用于编写Shell脚本,其中包含了Shell解释器的语法和特性,而Exec格式则主要用于编写可执行程序或直接在命令行中执行的命令,其中包含了特定命令或程序的语法和选项。两者在语法和用途上有所不同,但都是在编写和执行命令时常用的格式。

  • 以下是一些使用Shell格式和Exec格式的Dockerfile命令的示例:
# 使用Shell格式的RUN命令,在容器中执行Shell命令
RUN apt update && apt install -y nginx

# 使用Shell格式的CMD命令,在容器启动时执行Shell命令
CMD service nginx start

# 使用Exec格式的ENTRYPOINT命令,指定容器启动时执行的可执行程序
ENTRYPOINT ["nginx", "-g", "daemon off;"]

通常来说,对于需要执行复杂的Shell命令或包含逻辑操作符的命令,可以使用Shell格式的命令;而对于需要指定可执行程序及其参数的情况,可以使用Exec格式的命令。

  • 最佳实践:

(1)使用RUN指令安装应用和软件包,构建镜像。
(2)如果Docker镜像的用途是运行应用程序或服务,比如运行一个MySQL,应该优先使用Exec格式的ENTRYPOINT指令。CMD可为ENTRYPOINT提供额外的默认参数,同时可利用docker run命令行替换默认参数。
(3)如果想为容器设置默认的启动命令,可使用CMD指令。用户可在docker run命令行中替换此默认命令。

3.构建步骤

  • 创建一个新的目录,并在该目录下创建一个名为Dockerfile的文件,用于构建新的Docker镜像。
mkdir nginx-image
cd nginx-image
touch Dockerfile
  • 使用文本编辑器(如nano或vim)打开Dockerfile,并添加以下内容:
# 使用官方的Ubuntu镜像作为基础镜像
FROM ubuntu

# 更新Ubuntu软件包列表并安装Nginx
RUN apt update && apt install -y nginx

# 暴露Nginx的80端口
EXPOSE 80

# 启动Nginx服务
CMD ["nginx", "-g", "daemon off;"]
  • 保存并关闭Dockerfile文件后,构建新的Docker镜像。在nginx-image目录下执行以下命令:

这将使用Dockerfile中的指令构建一个新的Docker镜像,并将其命名为my-nginx-image。

docker build: 使用 Dockerfile 构建一个新的镜像。
-t my-nginx-image: 为构建的镜像指定一个名称为 my-nginx-image。
.: 表示 Docker 在当前目录中查找 Dockerfile 来构建镜像。

sudo docker build -t my-nginx-image .
  • 使用以下命令来查看新创建的镜像:
sudo docker images
  • 可以基于新创建的镜像来运行一个Nginx容器:
sudo docker run -d -p 80:80 my-nginx-image

三、使用构建的镜像

1.使用步骤

  • 如何在多个Docker Host上使用镜像?

(1)用相同的Dockerfile在其他host构建镜像。
(2)将镜像上传到公共Registry(比如Docker Hub), Host直接下载使用。
(3)搭建私有的Registry供本地Host使用。

  • 使用公共Registry:

Docker Hub是Docker公司维护的公共Registry。用户可以将自己的镜像保存到Docker Hub免费的repository中。如果不希望别人访问自己的镜像,也可以购买私有repository。

  • 搭建本地的Registry:

安装Docker Registry

docker run -d -p 5000:5000 --restart=always --name my-registry registry:2

配置Docker客户端: 接下来,你需要配置Docker客户端,以便它能够与本地的Registry进行交互。你可以通过编辑Docker配置文件(通常是/etc/docker/daemon.json)来添加Registry的地址,将your-registry-domain替换为你的Registry所在的域名或IP地址。

   {
     "insecure-registries" : ["your-registry-domain:5000"]
   }

使用docker push命令将本地构建的镜像推送到你的Registry中,也可以使用docker pull命令从Registry中拉取镜像。

   docker tag my-image your-registry-domain:5000/my-image:v1.0
   docker push your-registry-domain:5000/my-image:v1.0
   docker pull your-registry-domain:5000/my-image:v1.0

docker tag: 这是用于给 Docker 镜像打标签的命令。
my-image: 这是要被标记的现有镜像的名称或 ID。
your-registry-domain:5000/my-image:v1.0.: 这是新的名称,指定了镜像的目标位置、名称、版本。

注意:镜像一定要按照规范(host:port/镜像名)命名,否则push会被拒绝。

2.镜像常用命令

当使用Docker时,有一些常用的镜像命令可以帮助你管理和操作Docker镜像。以下是一些常用的Docker镜像命令及其功能:

  1. docker images

    • 这个命令用于列出本地系统上的所有Docker镜像。
    • 示例:docker images
  2. docker pull

    • 从远程仓库拉取Docker镜像到本地系统。
    • 示例:docker pull ubuntu:latest
  3. docker build

    • 使用Dockerfile构建Docker镜像。
    • 示例:docker build -t my-image .
  4. docker tag

    • 为镜像添加一个标签。
    • 示例:docker tag my-image my-registry-domain:5000/my-image:v1.0
  5. docker push

    • 将本地的镜像推送到远程仓库。
    • 示例:docker push my-registry-domain:5000/my-image:v1.0
  6. docker rmi

    • 删除本地的一个或多个镜像。
    • 示例:docker rmi my-image
  7. docker inspect

    • 显示关于镜像的详细信息,包括镜像的元数据和配置。
    • 示例:docker inspect my-image
  8. docker history

    • 显示镜像的历史记录,包括每一层的创建者和命令。
    • 示例:docker history my-image
  9. docker savedocker load

    • docker save用于将一个或多个镜像保存为tar归档文件。
    • docker load用于从tar归档文件中加载镜像。
    • 示例:docker save -o my-images.tar my-imagedocker load -i my-images.tar

这些命令可以帮助你管理Docker镜像,包括拉取、构建、推送、删除、查看详细信息等操作。通过熟练掌握这些命令,你可以更好地管理和使用Docker镜像。

文章来源:https://blog.csdn.net/Tracycoder/article/details/135001781
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。