Dawn's Blogs

分享技术 记录成长

0%

Docker学习笔记 (2) 镜像操作

使用镜像

搜索镜像

使用docker search命令可以搜索镜像:

1
2
3
4
5
6
7
8
$ docker search redis
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
redis Redis is an open source key-value store that… 11669 [OK]
bitnami/redis Bitnami Redis Docker Image 236 [OK]
redislabs/redisinsight RedisInsight - The GUI for Redis 75
redislabs/redisearch Redis With the RedisSearch module pre-loaded… 56
redislabs/rejson RedisJSON - Enhanced JSON data type processi… 51
redislabs/redis Clustered in-memory database engine compatib… 36

获取镜像

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

1
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

使用 docker run 命令可以运行容器。

列出镜像

要想列出已经下载下来的镜像,可以使用 docker image 命令:

1
2
3
C:\Users\63544>docker image
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 5a214d77f5d7 7 months ago 63.1MB

REPOSITORY:表示镜像的仓库源
TAG:镜像的标签版本号
IMAGE ID:镜像ID
CREATED:镜像创建时间
SIZE:镜像大小


注意:

docker image 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。


虚悬镜像

由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 <none> 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image)

中间层镜像

为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。所以在使用一段时间后,可能会看到一些依赖的中间层镜像。无标签镜像都是中间层镜像。

删除镜像

可以用 docker image rm 命令删除本地镜像:

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

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

Untagged 和 Deleted

如果删除某个镜像,命令行分为两类: Untagged 和 Deleted

  • Untagged:将要求的所有镜像标签都取消,因为一个镜像可以对应多个标签,因此当我们删除了所指定的标签后,可能还有别的标签指向了这个镜像,如果是这种情况,那么 Delete 行为就不会发生。

  • Deleted:当该镜像所有的标签都被取消了,就会触发删除行为。因为镜像是多层存储结构,因此很有可能某个其它镜像正依赖于当前镜像的某一层。这种情况,依旧不会触发删除该层的行为。直到没有任何层依赖当前层时,才会真实的删除当前层。

    1
    2
    3
    4
    # 普通删除
    docker rmi 镜像名字/ID
    # 强制删除,可以删除已经停止的容器对应的镜像
    docker rmi -f 镜像名字/ID

commit命令

docker commit 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。语法格式:

1
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]

注意,慎用 commit 命令:

  • 使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。
  • 会使镜像更加臃肿:如果使用 docker commit 制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。

构建镜像 Dockerfile

Dockerfile是一个文本文件(脚本),其内包含了一条条的 指令(Instruction)每一条指令对应一层镜像,这些指令描述如何构建当前层。

image-20221225120610835

如:

1
2
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • From 指定基础层。
  • RUN 指令是用来执行命令行命令的。

可以利用 docker build 命令构建镜像:

docker build [选项] <上下文路径/URL/->

RUN 构建时需要运行的命令

格式:

1
2
RUN <命令行命令>
RUN ["可执行文件", "参数1", "参数2"...]

RUN是在 docker build时运行

COPY 复制文件

格式:

1
COPY [--chown=<user>:<group>] <源路径>... <目标路径>

COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。

ADD 更高级的复制文件

ADDCOPY的格式 基本一样,只是 ADD 命令增加了一些功能:

  • <源路径> 可以是一个 URL,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。
  • <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。

因此在 COPYADD 指令中选择的时候,可以遵循这样的原则

所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD


CMD 容器启动命令

CMD 指令格式:

1
CMD ["可执行文件", "参数1", "参数2"...]

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

注意:

  • 最后一个 CMD 会被 docker run 之后的参数替换

CMD 和 RUN 的区别:

  • CMD是在docker run 时运行。
  • RUN是在 docker build时运行。

ENTRYPOINT 入口点

当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令:

1
2
ENTRYPOINT ["可执行文件", "参数1", "参数2"...]
<ENTRYPOINT> "<CMD>"

ENTRYPOINT不会被docker run后面的命令覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。这样在执行docker run的时候,可以指定 ENTRYPOINT 运行所需的参数

ENV 设置环境变量

格式:

1
ENV <key1>=<value1> <key2>=<value2>...

ARG 构建参数

格式:

1
ARG <参数名>[=<默认值>]

构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时不会存在这些环境变量的。

VOLUME 定义匿名卷

1
VOLUME ["<路径1>", "<路径2>"...]

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于(volume)中。

为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

EXPOSE 声明端口

1
EXPOSE <端口1> [<端口2>...]

EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。这样做有两个好处:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

WORKDIR 指定工作目录

1
WORKDIR <工作目录路径>

USER 指定当前用户

1
USER <用户名>[:<用户组>]