Docker学习二:镜像、容器、仓库相关操作

一、镜像的相关操作

Docker学习二:镜像、容器、仓库相关操作_第1张图片

Docker镜像的操作可以分为:

  • 拉取镜像,使用docker pull命令拉取远程仓库的镜像到本地 ;
  • 重命名镜像,使用docker tag命令“重命名”镜像 ;
  • 查看镜像,使用docker image lsdocker images命令查看本地已经存在的镜像 ;
  • 删除镜像,使用docker rmi命令删除无用镜像 ;
  • 构建镜像,构建镜像有两种方式。第一种方式是使用docker build命令基于 Dockerfile 构建镜像,也是我比较推荐的镜像构建方式;第二种方式是使用docker commit命令基于已经运行的容器提交为镜像。

1. 拉取镜像

命令格式:docker pull [Registry]/[Repository]/[Image]:[Tag]

  • Registry 为注册服务器,Docker 默认会从 docker.io 拉取镜像,如果有自己的镜像仓库(如Harbor),可以把 Registry 替换为自己的注册服务器。
  • Repository 为镜像仓库,通常把一组相关联的镜像归为一个镜像仓库,library为 Docker 默认的镜像仓库。
  • Image 为镜像名称。
  • Tag 为镜像的标签,如果不指定拉取镜像的标签,默认为latest

以拉取busybox 镜像为例,busybox 是一个集成了数百个 Linux 命令(例如 curl、grep、mount、telnet 等)的精简工具箱,只有几兆大小

$ docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
61c5ed1cbdf8: Pull complete
Digest: sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest

实际执行docker pull命令,都是先从本地搜索,如果本地搜索不到busybox镜像则从 Docker Hub 下载镜像

2. 查看镜像

命令:docker images或者docker image ls

# 列出本地所有的镜像
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              4bb46517cac3        9 days ago          133MB
nginx               1.15                53f3fd8007f7        15 months ago       109MB
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB

# 查询指定的镜像
$ docker image ls busybox
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB

# 列出所有镜像,然后使用grep命令进行过滤
$ docker images | grep busybox
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB

3. 重命名镜像

如果想要自定义镜像名称或者推送镜像到其他镜像仓库,可以使用docker tag命令将镜像重命名。

命令:docker tag [SOURCE_IMAGE][:TAG] [TARGET_IMAGE][:TAG]

# 将busybox镜像重命名
$ docker tag busybox:latest mybusybox:latest

# 查本地看镜像
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              018c9d7b792b        3 weeks ago         1.22MB
mybusybox           latest              018c9d7b792b        3 weeks ago         1.22MB

busybox和mybusybox这两个镜像的 IMAGE ID 是完全一样的,实际上它们指向了同一个镜像文件,只是别名不同而已。

4. 删除镜像

命令:docker rmi

$ docker rmi mybusybox
Untagged: mybusybox:latest

5. 构建镜像

命令:

  • docker commit:从运行中的容器提交为镜像
  • docker build:从 Dockerfile 构建镜像

先介绍第一种:docker commit,格式:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

  • OPTIONS包括:-a :提交的镜像作者;-c :使用Dockerfile指令来创建镜像;-m :提交时的说明文字;-p :在commit时,将容器暂停。
  • CONTAINER 为容器名称
# 使用 busybox 镜像创建一个名为 busybox 的容器并进入 busybox 容器
$ docker run --rm --name=busybox -it busybox sh

# 在容器中,执行以下命令创建一个文件并写入内容
/ # touch hello.txt && echo "I love Docker. " > hello.txt

# 新打开另一个命令行窗口,运行以下命令提交镜像
$ docker commit busybox busybox:hello
sha256:cbc6406aaef080d1dd3087d4ea1e6c6c9915ee0ee0f5dd9e0a90b03e2215e81c

# 查看镜像
$ docker image ls busybox
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             hello               cbc6406aaef0        2 minutes ago       1.22MB
busybox             latest              018c9d7b792b        4 weeks ago         1.22MB

再介绍第二种:docker build,格式:docker build [OPTIONS]

  • OPTIONS包括:
    –build-arg,设置构建时的变量
    –no-cache,默认false。设置该选项,将不使用Build Cache构建镜像
    –pull,默认false。设置该选项,总是尝试pull镜像的最新版本
    –compress,默认false。设置该选项,将使用gzip压缩构建的上下文
    –disable-content-trust,默认true。设置该选项,将对镜像进行验证
    –file, -f,Dockerfile的完整路径,默认值为‘PATH/Dockerfile’
    –isolation,默认–isolation=“default”,即Linux命名空间;其他还有process或hyperv
    –label,为生成的镜像设置metadata
    –squash,默认false。设置该选项,将新构建出的多个层压缩为一个新层,但是将无法在多个镜像之间共享新层;设置该选项,实际上是创建了新image,同时保留原有image。
    –tag, -t,镜像的名字及tag,通常name:tag或者name格式;可以在一次构建中为一个镜像设置多个tag
    –network,默认default。设置该选项,Set the networking mode for the RUN instructions during build
    –quiet, -q,默认false。设置该选项,Suppress the build output and print image ID on success
    –force-rm,默认false。设置该选项,总是删除掉中间环节的容器
    –rm,默认–rm=true,即整个构建过程成功后删除中间环节的容器
  • PATH | URL | -
    从Docker文件和“上下文”构建Docker映像。 构建的上下文是位于指定PATH或URL中的文件。
    URL参数可以指三种资源:Git存储库,压缩包上下文和纯文本文件
    -表示通过STDIN给出Dockerfile或上下文
# 假如有一个 Dockerfile,内容如下:
FROM centos:7
COPY nginx.repo /etc/yum.repos.d/nginx.repo
RUN yum install -y nginx
EXPOSE 80
ENV HOST=mynginx
CMD ["nginx","-g","daemon off;"]

# 根据该Dockerfile构建镜像如下,其中.代表当前文件夹
docker build -t mynginx:test .

二、Dockerfile

在Docker镜像构建的方法中,提到可以通过Dockerfile进行镜像的构建。这里对Dockerfile以及Dockerfile的命令进行介绍。Dockerfile 是一个包含了用户所有构建命令的文本,通过docker build命令可以从 Dockerfile 生成镜像。

Dockerfile的命令有很多,以下进行介绍。

FROM:指定基础image
FROM 
FROM :
MAINTAINER:指定镜像创建者信息
MAINTAINER 
RUN:安装软件用,RUN可以运行任何被基础image支持的命令
RUN  (在 shell 终端中运行命令,即/bin/sh -c)
RUN ["executable", "param1", "param2" ... ] (exec 执行)
CMD:设置container启动时执行的操作
CMD command param1 param2
CMD ["executable","param1","param2"]
当Dockerfile指定了ENTRYPOINT,CMD提供给ENTRYPOINT 默认参数:CMD ["param1","param2"]
ENTRYPOINT:设置container启动时执行的操作(不可被docker run提供的参数覆盖)
每个Dockerfile 中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
USER:设置container容器的用户,默认是root用户
USER daemon
EXPOSE:指定容器需要映射到宿主机器的端口
EXPOSE  [...]
ENV:用于设置环境变量
ENV  
ADD:将源文件复制到container的目标文件
ADD  :复制指定的到容器中的可以是Dockerfile所在目录的一个相对路径;也可以是一个 URL;还可以是一个 tar 文件;
是container中的绝对路径
COPY:将源文件复制到container的目标文件,但不会做自动解压工作
COPY  
VOLUME:指定挂载点,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用
VOLUME [""]
WORKDIR:切换目录,相当于cd命令
WORKDIR /path/to/workdir
ONBUILD:在子镜像中执行
ONBUILD 
ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行。

三、镜像的实现原理

Docker 镜像是由一系列镜像层(layer)组成的,每一层代表了镜像构建过程中的一次提交

以一个镜像构建的 Dockerfile 来说明镜像是如何分层的,Dockerfile 的内容如下:

# 基于 busybox 创建一个镜像层
FROM busybox
# 拷贝本机 test 文件到镜像内
COPY test /tmp/test
# 在 /tmp 文件夹下创建一个目录 testdir
RUN mkdir /tmp/testdir

以Dockerfile 为基础进行镜像的构建

docker build -t mybusybox .

如果Docker使用的是overlay2 文件驱动,进入到/var/lib/docker/overlay2目录下使用tree .命令查看产生的镜像文件:

$ tree .
# 以下为 tree . 命令输出内容
|-- 3e89b959f921227acab94f5ab4524252ae0a829ff8a3687178e3aca56d605679
|   |-- diff  # 这一层为基础层,对应上述 Dockerfile 第一行,包含 busybox 镜像所有文件内容,例如 /etc,/bin,/var 等目录
... 此次省略部分原始镜像文件内容
|   `-- link 
|-- 6591d4e47eb2488e6297a0a07a2439f550cdb22845b6d2ddb1be2466ae7a9391
|   |-- diff   # 这一层对应上述 Dockerfile 第二行,拷贝 test 文件到 /tmp 文件夹下,因此 diff 文件夹下有了 /tmp/test 文件
|   |   `-- tmp
|   |       `-- test
|   |-- link
|   |-- lower
|   `-- work
|-- backingFsBlockDev
|-- bec6a018080f7b808565728dee8447b9e86b3093b16ad5e6a1ac3976528a8bb1
|   |-- diff  # 这一层对应上述 Dockerfile 第三行,在 /tmp 文件夹下创建 testdir 文件夹,因此 diff 文件夹下有了 /tmp/testdir 文件夹
|   |   `-- tmp
|   |       `-- testdir
|   |-- link
|   |-- lower
|   `-- work
...

Dockerfile 的每一行命令,都生成了一个镜像层,每一层的 diff 夹下只存放了增量数据,如图所示

Docker学习二:镜像、容器、仓库相关操作_第2张图片

Docker 镜像是静态的分层管理的文件组合,镜像底层的实现依赖于联合文件系统(UnionFS)。.分层的结构使得 Docker 镜像非常轻量,每一层根据镜像的内容都有一个唯一的 ID 值,当不同的镜像之间有相同的镜像层时,便可以实现不同的镜像之间共享镜像层的效果。

四、容器的相关操作

容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个容器层,该层允许修改镜像的整个副本。

Docker学习二:镜像、容器、仓库相关操作_第3张图片

容器的生命周期是容器可能处于的状态,容器的生命周期分为 5 种:

  • created:初建状态
  • running:运行状态
  • stopped:停止状态
  • paused: 暂停状态
  • deleted:删除状态
    容器生命周期之间的转换关系如下:
Docker学习二:镜像、容器、仓库相关操作_第4张图片

通过不同的docker命令可以实现容器状态之间的转换,下面对容器相关的操作命令进行介绍:

1. 创建容器

命令:docker create [OPTIONS] IMAGE [COMMAND] [ARG…]

  • OPTIONS:
    -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
    -d: 后台运行容器,并返回容器ID;
    -i: 以交互模式运行容器,通常与 -t 同时使用;
    -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
    –name=“nginx-lb”: 为容器指定一个名称;
    –dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
    –dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
    -h “mars”: 指定容器的hostname;
    -e username=“ritchie”: 设置环境变量;
    –env-file=[]: 从指定文件读入环境变量;
    –cpuset=“0-2” or --cpuset=“0,1,2”: 绑定容器到指定CPU运行;
    -m :设置容器使用内存最大值;
    –net=“bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
    –link=[]: 添加链接到另一个容器;
    –expose=[]: 开放一个端口或一组端口;
$ docker create -it --name=busybox busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
61c5ed1cbdf8: Pull complete
Digest: sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977
Status: Downloaded newer image for busybox:latest
2c2e919c2d6dad1f1712c65b3b8425ea656050bd5a0b4722f8b01526d5959ec6

2. 启动容器

有两种启动容器的方式:

  • 使用docker start命令基于已经创建好的容器直接启动 。
  • 使用docker run命令直接基于镜像新建一个容器并启动,相当于先执行docker create命令从镜像创建容器,然后再执行docker start命令启动容器。

方式一:docker start,格式:docker start [OPTIONS] CONTAINER [CONTAINER…]

$ docker start busybox

方式二:docker run,格式:docker run [OPTIONS] IMAGE [COMMAND] [ARG…],OPTIONS参照docker create命令

# -t 参数的作用是分配一个伪终端,-i 参数则可以终端的 STDIN 打开,同时使用 -it 参数可以让我们进入交互模式。
$ docker run -it --name=busybox busybox

# 交互模式下可以通过所创建的终端来输入命令
$ ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sh
    6 root      0:00 ps aux
# 容器的 1 号进程为 sh 命令,在容器内部并不能看到主机上的进程信息,因为容器内部和主机是完全隔离的
# 由于 sh 是 1 号进程,意味着如果通过 exit 退出 sh,那么容器也会退出。所以对于容器来说,杀死容器中的主进程,则容器也会被杀死。

3. 终止容器

命令:docker stop,格式:docker stop [OPTIONS] CONTAINER [CONTAINER…]

  • Options参数包含:-t, --time,杀死容器之前等待停止的秒数(默认为10)

该命令首先会向运行中的容器发送 SIGTERM 信号,如果容器内 1 号进程接受并能够处理 SIGTERM,则等待 1 号进程处理完毕后退出,如果等待一段时间后,容器仍然没有退出,则会发送 SIGKILL 强制终止容器。

$ docker stop busybox
busybox

# 查看停止状态的容器信息
$ docker ps -a
CONTAINERID       IMAGE      COMMAND            CREATED             STATUS     PORTS         NAMES
28d477d3737a        busybox             "sh"                26 minutes ago      Exited (137) About a minute ago                       busybox

# 也可以通过docker start命令来重新启动
$ docker start busybox
busybox

# docker restart命令会将一个运行中的容器终止,并且重新启动它
$ docker restart busybox
busybox

4. 进入容器

处于运行状态的容器可以通过docker attachdocker exec等多种方式进入容器

方式一:docker attach,格式:docker attach [OPTIONS] CONTAINER

$ docker attach busybox
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sh
    7 root      0:00 ps aux
/ #

当同时使用docker attach命令同时在多个终端运行时,所有的终端窗口将同步显示相同内容,当某个命令行窗口的命令阻塞时,其他命令行窗口同样也无法操作

方式二:docker exec,格式:docker exec [OPTIONS] container_name COMMAND [ARG…]

  • OPTIONS说明:
    -d,以后台方式执行命令;
    -e,设置环境变量
    -i,交互模式
    -t,设置TTY
    -u,用户名或UID,例如myuser:myusergroup
$ docker exec -it busybox sh
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sh
    7 root      0:00 sh
   12 root      0:00 ps aux
# 容器内有两个sh进程,这是因为以exec的方式进入容器,会单独启动一个 sh 进程

当同时使用docker exec命令同时在多个终端运行时,每个窗口都是独立且互不干扰的,docker exec命令也是使用最多的一种方式。

5. 删除容器

命令:docker rm,格式:docker rm [OPTIONS] CONTAINER [CONTAINER…]

  • OPTIONS说明:
    -f :通过 SIGKILL 信号强制删除一个运行中的容器。
    -l :移除容器间的网络连接,而非容器本身。
    -v :删除与容器关联的卷。
# 删除一个停止状态的容器
docker rm busybox

# 删除正在运行中的容器
docker rm -f busybox

6. 导入/导出容器

导出容器命令:docker export,格式:docker export [OPTIONS] CONTAINER

  • OPTIONS说明:
    -o :将输入内容写到文件
# 进入容器创建文件
docker exec -it busybox sh
cd /tmp && touch test

# 执行导出命令
docker export busybox > busybox.tar

执行以上命令后会在当前文件夹下生成 busybox.tar 文件,可以将该文件拷贝到其他机器上,通过导入命令实现容器的迁移。

导入容器命令:docker import,格式:docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

  • OPTIONS说明:
    -c :应用docker 指令创建镜像
    -m :提交时的说明文字
docker import busybox.tar busybox:test
# 执行完docker import后会变为本地镜像

五、仓库相关操作

注册服务器(Registry)VS 仓库(Repository)

  • 注册服务器是存放仓库的实际服务器,而仓库则可以被理解为一个具体的项目或者目录;
  • 注册服务器可以包含很多个仓库,每个仓库又可以包含多个镜像。例如我的镜像地址为 docker.io/centos,docker.io 是注册服务器,centos 是仓库名
Docker学习二:镜像、容器、仓库相关操作_第5张图片

1. 公共镜像仓库

公共镜像仓库一般是 Docker 官方或者其他第三方组织(阿里云,腾讯云,网易云等)提供的,允许所有人注册和使用的镜像仓库。

Docker Hub 是全球最大的镜像市场,目前已经有超过 10w 个容器镜像,这些容器镜像主要来自软件供应商、开源组织和社区。大部分的操作系统镜像和软件镜像都可以直接在 Docker Hub 下载并使用。

以Docker Hub 为例,要使用Docker Hub公共镜像仓库,需要先在Docker Hub官网注册账号并创建自己的仓库,以方便后续管理镜像,具体操作此处不做赘述。

在用Docker Hub管理镜像之前,需要先登录镜像服务器,命令为docker login,Docker 会要求输入用户名和密码,输入注册的账号和密码,看到Login Succeeded表示登录成功。登录成功后就可以推送镜像到自己创建的仓库了。

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: lagoudocker
Password:
Login Succeeded

docker login命令默认会请求 Docker Hub,如果想登录第三方镜像仓库或者自建的镜像仓库,在docker login后面加上注册服务器即可。例如想登录访问阿里云镜像服务器,则使用docker login registry.cn-beijing.aliyuncs.com,输入阿里云镜像服务的用户名密码即可。

接着就可以利用Docker Hub对镜像进行管理

# 拉取镜像
$ docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
Digest: sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977
Status: Image is up to date for busybox:latest
docker.io/library/busybox:latest

# 镜像“重命名
$ docker tag busybox lagoudocker/busybox

# 推送镜像
$ docker push lagoudocker/busybox
The push refers to repository [docker.io/lagoudocker/busybox]
514c3a3e64d4: Mounted from library/busybox
latest: digest: sha256:400ee2ed939df769d4681023810d2e4fb9479b8401d97003c710d0e20f7c49c6 size: 527

其中,推送镜像的命令为:docker push,格式为:docker push [OPTIONS] NAME[:TAG]

  • OPTIONS说明:
    –disable-content-trust :忽略镜像的校验,默认开启

2. 私有镜像仓库

Docker 官方提供了开源的镜像仓库 Distribution,并且镜像存放在 Docker Hub 的 Registry 仓库下供我们下载。

先启动一个本地镜像仓库

$ docker run -d -p 5000:5000 --name registry registry:2.7
Unable to find image 'registry:2.7' locally
2.7: Pulling from library/registry
cbdbe7a5bc2a: Pull complete
47112e65547d: Pull complete
46bcb632e506: Pull complete
c1cc712bcecd: Pull complete
3db6272dcbfa: Pull complete
Digest: sha256:8be26f81ffea54106bae012c6f349df70f4d5e7e2ec01b143c46e2c03b9e551d
Status: Downloaded newer image for registry:2.7
d7e449a8a93e71c9a7d99c67470bd7e7a723eee5ae97b3f7a2a8a1cf25982cc3

# 查看启动的容器
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
d7e449a8a93e        registry:2.7        "/entrypoint.sh /etc…"   50 seconds ago      Up 49 seconds       0.0.0.0:5000->5000/tcp   registry
# 启动的私有镜像仓库,访问地址为localhost,端口号为 5000

推送镜像到本地仓库

#  镜像"重命名"
$ docker tag busybox localhost:5000/busybox

# 推送镜像
$ docker push localhost:5000/busybox
The push refers to repository [localhost:5000/busybox]
514c3a3e64d4: Layer already exists
latest: digest: sha256:400ee2ed939df769d4681023810d2e4fb9479b8401d97003c710d0e20f7c49c6 size: 527

# 删除本地的busybox和localhost:5000/busybox镜像
$ docker rmi busybox localhost:5000/busybox
Untagged: busybox:latest
Untagged: busybox@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977
Untagged: localhost:5000/busybox:latest
Untagged: localhost:5000/busybox@sha256:400ee2ed939df769d4681023810d2e4fb9479b8401d97003c710d0e20f7c49c6

# 从本地镜像仓库拉取busybox镜像
$ docker pull localhost:5000/busybox
Using default tag: latest
latest: Pulling from busybox
Digest: sha256:400ee2ed939df769d4681023810d2e4fb9479b8401d97003c710d0e20f7c49c6
Status: Downloaded newer image for localhost:5000/busybox:latest
localhost:5000/busybox:latest

由于容器是无状态的,私有仓库的启动方式可能会导致镜像丢失,因为我们并没有把仓库的数据信息持久化到主机磁盘上。可以采用docker卷(后续章节进行介绍)的方式进行持久化。

$ docker run -v /var/lib/registry/data:/var/lib/registry -d -p 5000:5000 --name registry registry:2.7

-v的含义是把 Docker 容器的某个目录或文件挂载到主机上,保证容器被重建后数据不丢失。-v参数冒号前面为主机目录,冒号后面为容器内目录。

这里的镜像仓库虽然可以本地访问和拉取,但是如果在另外一台机器上是无法通过 Docker 访问到这个镜像仓库的,因为 Docker 要求非localhost访问的镜像仓库必须使用 HTTPS,这时候就需要构建外部可访问的镜像仓库,具体步骤此处不再赘述。

Docker 官方开源的镜像仓库Distribution仅满足了镜像存储和管理的功能,用户权限管理相对较弱,并且没有管理界面。如果你想要构建一个企业的镜像仓库,Harbor 是一个非常不错的解决方案。Harbor 是一个基于Distribution项目开发的一款企业级镜像管理软件,拥有 RBAC (基于角色的访问控制)、管理用户界面以及审计等非常完善的功能。后续章节会介绍如何搭建Harbor私有镜像仓库。

你可能感兴趣的:(Docker学习系列,docker,学习,容器)