一、基本概念
1、docker镜像(Image)
- Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。
2、docker容器(Container)
- 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
3、docker仓库(Registry)
- 镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务所有就有了Docker Registry
二、镜像操作
1、获取镜像
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
:从仓库拉取镜像。-
- {
docker pull ubuntu:20.04
:拉取名为 ubuntu 标签是 20.04的镜像; docker pull ubuntu@sha256:12345abcdef...
: 拉取具有特定 SHA256 摘要的 ubuntu 镜像。}
2、列出镜像
docker image ls
:列出镜像- 虚悬镜像:由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image) ,可以使用下面的命令显示这类镜像:
docker image ls -f dangling=true
docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 00285df0df87 5 days ago 342 MB
docker image ls -a
:列出所有镜像,包括中间层镜像,就是没有标签的镜像docker image ls RegistryName
:根据仓库名称列出镜像docker image ls -f since=RegistryName:TAG
:列出在这个镜像之后建立的镜像【docker image ls -f since=ubuntu:20.04
:将会列出 ubuntu:20.04之后建立的镜像,若要列出之前建立的镜像将 since 换成before即可】
3、删除镜像
docker image rm [选项] <镜像1> [<镜像2> ...]
:删除镜像 【docker image rm 0584b3d2cf6d
:删除镜像ID是 0584b3d2cf6d 的镜像】
4、将当前容器状态保存为一个新的镜像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
:将当前容器状态保存为新的镜像 【docker commit -a "John Doe" -m "Added new features" my_container my_new_image
:将 my_container 容器保存为:my_new_image镜像】-
- 【OPTIONS说明:-a :提交的镜像作者;-c :使用 Dockerfile 指令来创建镜像;-m :提交时的说明文字;-p :提交镜像前暂停容器(默认为true)。】
5、将 Docker 镜像保存到 tar 归档文件中
docker save [OPTIONS] IMAGE [IMAGE...]
:将镜像保存为tar文件 【docker save -o myimage.tar myimage:latest
:将myimage镜像保存为myimag.tar】
IMAGE: 要保存的一个或多个镜像名称或 ID。
OPTIONS 说明:
-o, --output: 指定输出文件的路径。
6、将docker save保存的tar文件加载成docker镜像
docker load [OPTIONS] filename
:将tar文件加载为docker镜像 【docker load -i myimage.tar
:将myimage加载为docker镜像,也可以通过标准输入方式加载成镜像,如:cat myimage.tar | docker load
】- OPTIONS 说明:
-i, --input: 指定输入文件的路径。
-q, --quiet: 安静模式,减少输出信息。
三、使用 Dockerfile 定制镜像
1、FROM 指定基础镜像
- 所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指定的。而 FROM 就是指定 基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。
- 除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
FROM scratch
2、RUN 执行命令
- RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。其格式有两种:
-
- shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 RUN 指令就是这种格式。
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
-
- exec 格式:RUN [“可执行文件”, “参数1”, “参数2”],这更像是函数调用中的格式。
3、构建镜像
docker build [选项] <上下文路径/URL/->
:构建镜像- 【
docker build -t nginx:v3 .
使用 -t 指定镜像名称,其中 . 表示当前目录,这样是将当前目录指定为上下文路径,而Dockerfile就在这个路径下,所有不用单独指定。如果Dockerfile不在此目录下需要通过 -f 指定其具体目录。那么什么是上下文路径呢?上下文路径下存放了所有构建镜像需要的资源。当使用docker build构建时,会将上下文目录下所有的资源上传的docker引擎。例如在这条指令COPY ./package.json /app/
这并不是要复制执行 docker build 命令所在的目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json,而是复制 上下文(context) 目录下的 package.json。】
4、COPY 复制文件
COPY <源路径>... <目标路径>
:复制文件 【COPY package.json /usr/src/app/
,将主机中的package.json复制到镜像的 /usr/src/app/ 目录下】
5、CMD 容器启动命令
- Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。
- shell 格式:
CMD <命令>
- exec 格式:
CMD ["可执行文件", "参数1", "参数2"...]
6、ENV 设置环境变量
- 格式有两种:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
- 例子:
ENV NODE_VERSION 7.2.0
:设置NODE_VERSION值为 7.2.0。
7、VOLUME 定义匿名卷
- 格式如下:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
- 例子:
VOLUME /data
:这里的 /data 目录就会在容器运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。
8、EXPOSE 声明端口
- 格式为
EXPOSE <端口1> [<端口2>...]
- EXPOSE 指令是声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
- 要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
9、WORKDIR 指定工作目录
- 格式为
WORKDIR <工作目录路径>
- 使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
10、USER 指定当前用户
- 格式:
USER <用户名>[:<用户组>]
- USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。WORKDIR 是改变工作目录,USER 则是改变之后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。注意,USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。
11、HEALTHCHECK 健康检查
- 格式:
HEALTHCHECK [选项] CMD <命令>
:设置检查容器健康状况的命令
HEALTHCHECK NONE
:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令 - HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12 引入的新指令。
- HEALTHCHECK 支持下列选项:
-
--interval=<间隔>
:两次健康检查的间隔,默认为 30 秒;
-
--timeout=<时长>
:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
-
--retries=<次数>
:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。
- 假设我们有个镜像是个最简单的 Web 服务,我们希望增加健康检查来判断其 Web 服务是否在正常工作,我们可以用 curl 来帮助判断,其 Dockerfile 的 HEALTHCHECK 可以这么写:
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1
- 这里我们设置了每 5 秒检查一次(这里为了试验所以间隔非常短,实际应该相对较长),如果健康检查命令超过 3 秒没响应就视为失败,并且使用 curl -fs http://localhost/ || exit 1 作为健康检查命令。
12、SHELL 指令
- 格式:
SHELL ["executable", "parameters"]
- SHELL 指令可以指定 RUN ENTRYPOINT CMD 指令的 shell,Linux 中默认为 [“/bin/sh”, “-c”]
四、操作 Docker 容器
1、启动、终止、重启、暂停、恢复,容器
(1)、启动容器
- 启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(exited)的容器重新启动。
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
:创建并启动一个新容器- 常用参数说明:
-d: 后台运行容器并返回容器 ID。
-it: 交互式运行容器,分配一个伪终端。
--name: 给容器指定一个名称。
-p: 端口映射,格式为 host_port:container_port。
-v: 挂载卷,格式为 host_dir:container_dir。
--rm: 容器停止后自动删除容器。
--env 或 -e: 设置环境变量。
--network: 指定容器的网络模式。
--restart: 容器的重启策略(如 no、on-failure、always、unless-stopped)。
-u: 指定用户。
1. 基本使用
docker run ubuntu
拉取 ubuntu 镜像并在前台启动一个容器。
2. 后台运行容器
docker run -d ubuntu
在后台运行 ubuntu 容器并返回容器 ID。
3. 交互式运行并分配终端
docker run -it ubuntu /bin/bash
以交互模式运行 ubuntu 容器,并启动一个 Bash shell。
4. 指定容器名称
docker run --name my_container ubuntu
运行一个 ubuntu 容器,并将其命名为 my_container。
5. 端口映射
docker run -p 8080:80 nginx
将本地主机的 8080 端口映射到容器内的 80 端口,运行 nginx 容器。
6. 挂载卷
docker run -v /host/data:/container/data ubuntu
将主机的 /host/data 目录挂载到容器内的 /container/data 目录。
7. 设置环境变量
docker run -e MY_ENV_VAR=my_value ubuntu
设置环境变量 MY_ENV_VAR 的值为 my_value,运行 ubuntu 容器。
8. 使用网络模式
docker run --network host nginx
使用主机的网络模式运行 nginx 容器。
9. 指定重启策略
docker run --restart always nginx
设置容器的重启策略为 always,即使容器停止也会自动重启。
10. 指定用户
docker run -u user123 ubuntu
以 user123 用户运行 ubuntu 容器。
11. 组合多个选项
docker run -d -p 8080:80 -v /host/data:/data --name webserver nginx
后台运行一个命名为 webserver 的 nginx 容器,将主机的 8080 端口映射到容器的 80 端口,并将主机的 /host/data 目录挂载到容器的 /data 目录。
docker start [OPTIONS] CONTAINER [CONTAINER...]
:启动一个已存在并停止运行的容器 【docker start my_container
:启动已创建且被停止的名为:my_container的容器】
(2)、停止容器
docker stop [OPTIONS] CONTAINER [CONTAINER...]
:停止正在运行的容器【docker stop -t 30 my_container
:等待30秒后停止运行my_container容器,参数是可选的】docker kill [OPTIONS] CONTAINER [CONTAINER...]
:立即终止正在运行的容器 【docker kill my_container
:立即终止my_container】
(3)、重启容器
docker restart [OPTIONS] CONTAINER [CONTAINER...]
:重启容器 【docker restart -t 30 my_container
:等待30秒后重启容器】
(4)、暂停容器
docker pause CONTAINER [CONTAINER...]
:暂停运行容器 【docker pause my_container
:暂停运行my_container】
(5)、恢复容器
docker unpause CONTAINER [CONTAINER...]
:恢复运行容器 【docker unpause my_container
:恢复运行my_container】
2、进入容器
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
:进入容器- 常用参数
-d, --detach: 在后台运行命令。
--detach-keys: 覆盖分离容器的键序列。
-e, --env: 设置环境变量。
--env-file: 从文件中读取环境变量。
-i, --interactive: 保持标准输入打开。
--privileged: 给这个命令额外的权限。
--user, -u: 以指定用户的身份运行命令。
--workdir, -w: 指定命令的工作目录。
-t, --tty: 分配一个伪终端。
实例
1、在容器内运行命令:
docker exec my_container ls /app
在运行中的 my_container 容器内执行 ls /app 命令,列出 /app 目录的内容。
2、以交互模式运行命令:
docker exec -it my_container /bin/bash
在运行中的 my_container 容器内启动一个交互式的 Bash shell。-i 保持标准输入打开,-t 分配一个伪终端。
3、在后台运行命令:
docker exec -d my_container touch /app/newfile.txt
在运行中的 my_container 容器内后台执行 touch /app/newfile.txt 命令,创建一个新文件。
4、设置环境变量:
docker exec -e MY_ENV_VAR=my_value my_container env
在运行中的 my_container 容器内执行 env 命令,并设置环境变量 MY_ENV_VAR 的值为 my_value。
5、以指定用户身份运行命令:
docker exec -u user123 my_container whoami
在运行中的 my_container 容器内以 user123 用户身份执行 whoami 命令。
6、指定工作目录:
docker exec -w /app my_container pwd
在运行中的 my_container 容器内以 /app 目录为工作目录执行 pwd 命令。
3、导出和导入容器
docker export [OPTIONS] CONTAINER
:导出容器 【docker export -o my_container_backup.tar my_container
:-o 指定将my_container导出到my_container_backup.tar的快照文件】cat my_container_backup.tar | docker import - test/my_container:v1.0
:从容器快照文件中再导入为镜像- 注意:(1)、docker export 命令用于将 Docker 容器的文件系统导出为一个 tar 归档文件。(2)、docker export 命令主要用于备份或迁移容器的文件系统,而不包括 Docker 镜像的所有层和元数据。
4、删除容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]
:删除停止运行的容器- OPTIONS说明:
-f, --force: 强制删除正在运行的容器(使用 SIGKILL 信号)。
-l, --link: 删除指定的连接,而不是容器本身。
-v, --volumes: 删除容器挂载的卷。
5、列出容器
docker ps [OPTIONS]
:列出容器- OPTIONS说明:
-a, --all: 显示所有容器,包括停止的容器。
-q, --quiet: 只显示容器 ID。
-l, --latest: 显示最近创建的一个容器,包括所有状态。
-n: 显示最近创建的 n 个容器,包括所有状态。
--no-trunc: 不截断输出。
-s, --size: 显示容器的大小。
--filter, -f: 根据条件过滤显示的容器。
--format: 格式化输出。
6、获取 Docker 对象(容器、镜像、卷、网络等)的详细信息
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
:获取 Docker 对象(容器、镜像、卷、网络等)的详细信息 【docker inspect my_container
:获取my_container详细信息】- OPTIONS 说明:
-f, --format: 使用 Go 模板语法格式化输出。
--type: 返回指定类型的对象信息(可选类型:container、image、network、volume)。
7、docker日志
docker logs [OPTIONS] CONTAINER
:查看docker日志 【docker logs my_container
:显示my_container容器的日志】- OPTIONS说明:
-f, --follow: 跟随日志输出(类似于 tail -f)。
--since: 从指定时间开始显示日志。
-t, --timestamps: 显示日志时间戳。
--tail: 仅显示日志的最后部分,例如 --tail 10 显示最后 10 行。
--details: 显示提供给日志的额外详细信息。
--until: 显示直到指定时间的日志。
8、显示容器端口映射信息
docker port CONTAINER [PRIVATE_PORT[/PROTO]]
:显示容器端口映射信息
CONTAINER: 要查询端口映射的容器的名称或 ID。
PRIVATE_PORT (可选): 容器内部的端口号。
PROTO (可选): 协议类型(tcp 或 udp),默认是 tcp。
1、查看容器的所有端口映射:
docker port my_container
显示名为 my_container 的容器的所有端口映射信息。
2、查看特定端口的映射:
docker port my_container 80
显示名为 my_container 的容器内部的端口 80 映射到宿主机的哪个端口。
3、查看特定端口和协议的映射:
docker port my_container 80/tcp
显示名为 my_container 的容器内部的 TCP 端口 80 映射到宿主机的哪个端口。
9、容器与宿主机间文件复制
docker cp SRC_PATH CONTAINER:DEST_PATH
:从宿主机复制文件到容器 【docker cp /path/on/host my_container:/path/in/container
:将宿主机中的文件复制到容器中】docker cp CONTAINER:SRC_PATH DEST_PATH
:从容器复制文件到宿主机 【docker cp my_container:/path/in/container /path/on/host
:将容器中的文件复制到宿主机中】- 选项说明:
SRC_PATH: 源路径(可以是容器内的路径或宿主机的路径)。
CONTAINER: 容器的名称或 ID。
DEST_PATH: 目标路径(可以是容器内的路径或宿主机的路径)。