容器,镜像和仓库关系及命令

发布时间 2023-11-10 10:12:58作者: 圆子不方

前言

因软考高级的系统分析师考试中涉及到很多容器相关的知识,所以决定好好整理一下这部分的内容,加深理解!

概念

1.镜像:一个只读的文件和文件夹组合(静态的可读文件),是容器运行的基础,包含容器运行所需要的基础文件和配置信息(来源:自行制作,镜像仓库拉取docker hub)

2.容器:镜像的运行实体,有运行时所需要的可写文件层(容器状态:初建、运行、暂停、停止、删除)

容器各状态切换命令:(初建、运行、暂停、停止、删除)

3.仓库:仓库用来存储和分发docker镜像,包含共有仓库和私有仓库,docker官方仓库:Docker Hub

 

镜像,仓库和容器三者关系图:

 

docker架构:

 

通俗理解:

1、镜像可以把它看成Java中的类,而容器可以看做是类的实例化对象。 (镜像是文件,容器是进程)
    一个类可以有多个对象,同理,一个镜像可以有多个容器。
    
2、docker的整个生命周期有三部分组成:镜像(image)+容器(container)+仓库 (repository)。
    docker容器=镜像+可读层

 

下文转载出处:https://www.cnblogs.com/nm666/p/15264583.html

 

依据命令的用途对其进行分类(来源:《Docker:容器与容器云(第2版)》):

从docker命令使用出发,梳理出如图所示的命令结构图:

一、Docker镜像

操作系统分为 内核 和 用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套Ubuntu 18.04 最小系统的 root 文件系统。

Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。

1、从仓库获取镜像

从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:

$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

通过 docker pull --help 命令来看一下具体的『选项』命令:

$ docker pull --help

Usage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Pull an image or a repository from a registry

Options:
  -a, --all-tags                Download all tagged images in the repository
      --disable-content-trust   Skip image verification (default true)
      --platform string         Set platform if server is multi-platform capable
  -q, --quiet                   Suppress verbose output

示例:

# 从官方仓库获取ubuntu18.04的镜像
$ docker pull ubuntu:18.04
# 从网易镜像仓库获取mysql最新版本镜像
$ docker pull hub.c.163.com/library/mysql:latest

2、列出镜像

要想列出本地已经下载下来的镜像,可以使用 docker image ls 或 docker images命令。

$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
redis                latest              5f515359c7f8        5 days ago          183 MB
nginx                latest              05a60462f8ba        5 days ago          181 MB
mongo                3.2                 fe9198c04d62        5 days ago          342 MB
<none>               <none>              00285df0df87        5 days ago          342 MB
ubuntu               18.04               329ed837d508        3 days ago          63.3MB
ubuntu               bionic              329ed837d508        3 days ago          63.3MB

列表包含了 仓库名标签镜像 ID创建时间 以及 所占用的空间

镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个 标签。因此,在上面的例子中,可以看到 ubuntu:18.04 和 ubuntu:bionic 拥有相同的 ID,因为它们对应的是同一个镜像。

镜像体积

仔细观察,注意到, docker images 这里标识的所占用空间和在 Docker Hub 上看到的镜像大小不同。比如,ubuntu:18.04 镜像大小,在这里是 63.3MB,但是在 Docker Hub 显示的却是 25.47 MB

因为仓库中的镜像是压缩过的,在上传和下载过程中都是保持压缩状态,节省网络传输流量。

而本地通过 docker images 看到的是展开后的体积。

虚悬镜像

docker images 列出来的镜像,发现有一个特殊的镜像,这个镜像既没有仓库名,也没有标签,均为 <none>

REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
<none>               <none>              00285df0df87        5 days ago          342 MB

这个镜像原本是有镜像名和标签的,原来为 mongo:3.2,随着官方镜像维护,发布了新版本后,重新 docker pull mongo:3.2 时,mongo:3.2 这个镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消,从而成为了 <none>。除了 docker pull 可能导致这种情况,docker build 也同样可以导致这种现象。

由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 <none> 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image) ,可以用下面的命令专门显示这类镜像:

$ docker image ls -f dangling=true
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              00285df0df87        5 days ago          342 MB

一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用下面的命令删除。

$ docker image prune

中间层镜像

为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。列出中间层镜像:

$ docker image ls -a

这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。

不应该删除,被其他镜像所依赖;不用管,删除依赖对象后会连带删除。

列出部分镜像

根据仓库名列出镜像:

$ docker images ubuntu

指定仓库名和标签

$ docker images ubuntu:18.04

过滤器参数 --filter,简写 -f ,示例:

# 列出虚悬镜像
$ docker images -f dangling=true
# mongo:3.2之后建立的镜像
$ docker images -f since=mongo:3.2
# mongo:3.2之前建立的镜像
$ docker images -f before=mongo:3.2
# 通过lable过滤
$ docker images -f label=com.example.version=0.1

以特定格式显示

仅列出ID列,-q 参数

$ docker images -q

另外一些时候,我们可能只是对表格的结构不满意,希望自己组织列;或者不希望有标题,这样方便其它程序解析结果等,这就用到了 Go 的模板语法

$ docker image ls --format "{{.ID}}: {{.Repository}}"
5f515359c7f8: redis
05a60462f8ba: nginx
fe9198c04d62: mongo
00285df0df87: <none>
329ed837d508: ubuntu
329ed837d508: ubuntu
$ docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID            REPOSITORY          TAG
5f515359c7f8        redis               latest
05a60462f8ba        nginx               latest
fe9198c04d62        mongo               3.2
00285df0df87        <none>              <none>
329ed837d508        ubuntu              18.04
329ed837d508        ubuntu              bionic

3、删除镜像

要删除本地的镜像,可以使用 docker image rm 命令,其格式为:

$ docker image rm [选项] <镜像1> [<镜像2> ...]

其中,<镜像> 可以是 镜像短 ID镜像长 ID镜像名 或者 镜像摘要

示例:比如我们有如下镜像

$ docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
centos                      latest              0584b3d2cf6d        3 weeks ago         196.5 MB
redis                       alpine              501ad78535f0        3 weeks ago         21.03 MB
docker                      latest              cf693ec9b5c7        3 weeks ago         105.1 MB
nginx                       latest              e43d811ce2f4        5 weeks ago         181.5 MB

删除

# 长ID
$ docker image rm 501ad78535f0
# 短ID,即只输入部分ID 一般取前3个字符以上,只要足够区分于别的镜像就可以了。
$ docker image rm 501
# 镜像名删除
$ docker image rm centos
# 镜像摘要删除
$ docker images --digests
$ docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
# 用docker images命令配合
$ docker image rm $(docker images -q redis)
# 删除mongo:3.2之前创建的镜像
$ docker image rm $(docker images -q -f before=mongo:3.2)

4、构建镜像

创建镜像有三种方法,分别为【基于已有镜像创建】、【基于本地模板创建】以及【基于Dockerfile创建】

具体参考: https://blog.csdn.net/Yuzhang2046/article/details/131161274

5、查找镜像

要查找 Docker Hub 上的镜像,可以使用以下命令:

docker search <image-name>

搜索 MySQL 镜像可以使用以下命令:

docker search mysql
[root@ecs-32f7 ~]# docker search mysql
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   14221     [OK]
mariadb                         MariaDB Server is a high performing open sou…   5432      [OK]
percona                         Percona Server is a fork of the MySQL relati…   614       [OK]
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   818       [OK]
bitnami/mysql                   Bitnami MySQL Docker Image                      89                   [OK]
circleci/mysql                  MySQL is a widely used, open-source relation…   29
bitnami/mysqld-exporter                                                         5
ubuntu/mysql                    MySQL open source fast, stable, multi-thread…   49
cimg/mysql                                                                      0
rapidfort/mysql                 RapidFort optimized, hardened image for MySQL   23
rapidfort/mysql8-ib             RapidFort optimized, hardened image for MySQ…   9
google/mysql                    MySQL server for Google Compute Engine          23                   [OK]
hashicorp/mysql-portworx-demo                                                   0
rapidfort/mysql-official        RapidFort optimized, hardened image for MySQ…   7
newrelic/mysql-plugin           New Relic Plugin for monitoring MySQL databa…   1                    [OK]
databack/mysql-backup           Back up mysql databases to... anywhere!         86
linuxserver/mysql               A Mysql container, brought to you by LinuxSe…   38
bitnamicharts/mysql                                                             0
mirantis/mysql                                                                  0
docksal/mysql                   MySQL service images for Docksal - https://d…   0
linuxserver/mysql-workbench                                                     50
vitess/mysqlctld                vitess/mysqlctld                                1                    [OK]
eclipse/mysql                   Mysql 5.7, curl, rsync                          0                    [OK]
drupalci/mysql-5.5              https://www.drupal.org/project/drupalci         3                    [OK]
drupalci/mysql-5.7              https://www.drupal.org/project/drupalci         0
[root@ecs-32f7 ~]#

二、Docker容器

简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用。

1、启动容器

新建启动

$ docker run ubuntu:18.04 /bin/echo 'Hello world'

启动一个 bash 终端,允许用户进行交互.其中,-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i 则让容器的标准输入保持打开。

$ docker run -t -i ubuntu:18.04 /bin/bash

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

  • 检查本地是否存在指定的镜像,不存在就从 registry 下载
  • 利用镜像创建并启动一个容器
  • 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
  • 从地址池配置一个 ip 地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被终止

启动已终止容器

可以利用 docker container start 命令,直接将一个已经终止(exited)的容器启动运行。

$ docker container start b9198ea30925

容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。可以在伪终端中利用 ps 或 top 来查看进程信息。

root@ba267838cc1b:/# ps
  PID TTY          TIME CMD
    1 ?        00:00:00 bash
   11 ?        00:00:00 ps

可见,容器中仅运行了指定的 bash 应用。这种特点使得 Docker 对资源的利用率极高,是货真价实的轻量级虚拟化。

2、后台运行

使用 -d 参数运行容器。

$ docker run -d ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
77b2dc01fe0f3f1265df143181e7b9af5e05279a884f4776ee75350ea9d8017a

此时容器会在后台运行并不会把输出的结果 (STDOUT) 打印到宿主机上面(输出结果可以用 docker logs 查看)。

$ docker logs 77b

查看容器信息

# 查看正在运行的容器
$ docker container ls
$ docker ps
# 查看所有运行过的容器
$ docker ps -a

3、终止容器

可以使用 docker container stop 或者 docker stop 来终止一个运行中的容器。

处于终止状态的容器,可以通过 docker container start 命令来重新启动。

此外,docker container restart 命令会将一个运行态的容器终止,然后再重新启动它。

4、进入容器

在使用 -d 参数时,容器启动后会进入后台。需要进入容器进行操作,包括使用 docker attach 命令或 docker exec 命令,推荐使用 docker exec 命令。

attach命令

$ docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED        STATUS         PORTS                                   NAMES
218a71b508bf   base:v1   "/bin/bash"   2 months ago   Up 6 seconds   0.0.0.0:2333->22/tcp, :::2333->22/tcp   distracted_robinson
$ docker attach 218
[root@218a71b508bf /]# ls
bin  data  dev  etc  home  lib  lib64  media  mnt  nas  opt  proc  root  run  sbin  srv  sys  tmp  Users  usr  var
[root@218a71b508bf /]#

注意: 如果从这个 stdin 中 exit,会导致容器的停止。

exec命令

docker exec 后边可以跟多个参数,这里主要说明 -i -t 参数。

只用 -i 参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示符,但命令执行结果仍然可以返回。

当 -i -t 参数一起使用时,则可以看到我们熟悉的 Linux 命令提示符。

$ docker exec -i 218a bash
ls
bin
data
dev
etc
home
lib
lib64
media
mnt
nas
opt
proc
root
run
sbin
srv
sys
tmp
Users
usr
var
exit
$ docker exec -it 218a bash
[root@218a71b508bf /]# ls
8e13963c663a4bfe9fe4b873ffe35d47-6696_decode.py_  anaconda-post.log  bin  data  dev  etc  home  lib  lib64  media  mnt  nas  opt  proc  root  run  sbin  srv  sys  tmp  Users  usr  var
[root@218a71b508bf /]#

如果从这个 stdin 中 exit,不会导致容器的停止。这就是为什么推荐使用 docker exec 的原因。

5、导入和导出容器

导出容器

导出本地某个容器,可以使用 docker export 命令。

$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS               NAMES
7691a814370e        ubuntu:18.04        "/bin/bash"         36 hours ago        Exited (0) 21 hours ago                       test
$ docker export 7691a814370e > ubuntu.tar

这样将导出容器快照到本地文件。

导入容器

使用 docker import 从容器快照文件中再导入为镜像,例如:

$ cat ubuntu.tar | docker import - test/ubuntu:v1.0
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
test/ubuntu         v1.0                9d37a6082e97        About a minute ago   171.3 MB

此外,也可以通过指定 URL 或者某个目录来导入,例如:

$ docker import http://example.com/exampleimage.tgz example/imagerepo

注:用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。

6、删除容器

使用 docker container rm 来删除一个处于终止状态的容器。例如:

$ docker container rm mysql
mysql

如果要删除一个运行中的容器,可以添加 -f 参数。Docker 会发送 SIGKILL 信号给容器。

$ docker container rm -f mysql

清除所有终止状态的容器

$ docker container prune

三、Docker仓库

仓库(Repository)是集中存放镜像的地方。

一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 docker.io/ubuntu 来说,docker.io 是注册服务器地址,ubuntu 是仓库名。

大部分时候,并不需要严格区分这两者的概念。

1、Docker Hub

目前 Docker 官方维护了一个公共仓库 Docker Hub (opens new window),其中已经包括了数量超过 8,250,000 (opens new window)的镜像。大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。

注册

https://hub.docker.com

登录

可以通过执行 docker login 命令交互式的输入用户名及密码来完成在命令行界面登录 Docker Hub。

通过 docker logout 退出登录。

拉取镜像

以通过 docker search 命令来查找官方仓库中的镜像,并利用 docker pull 命令来将它下载到本地。

例如以 centos 为关键词进行搜索:

$ docker search centos
NAME                               DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                             The official build of CentOS.                   6449      [OK]
ansible/centos7-ansible            Ansible on Centos7                              132                  [OK]
consol/centos-xfce-vnc             Centos container with "headless" VNC session…   126                  [OK]
jdeathe/centos-ssh                 OpenSSH / Supervisor / EPEL/IUS/SCL Repos - …   117                  [OK]
centos/systemd                     systemd enabled base container.                 96                   [OK]

推送镜像

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

以下命令中的 username 请替换为你的 Docker 账号用户名。

$ docker tag ubuntu:18.04 username/ubuntu:18.04

$ docker image ls

REPOSITORY                                               TAG                    IMAGE ID            CREATED             SIZE
ubuntu                                                   18.04                  275d79972a86        6 days ago          94.6MB
username/ubuntu                                          18.04                  275d79972a86        6 days ago          94.6MB

$ docker push username/ubuntu:18.04

$ docker search username

NAME                      DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
username/ubuntu

2、私有仓库

 

四、参考