Docker 学习笔记
Docker 简介
Docker是一个开源的容器引擎,它可以帮助我们更快地交付应用。Docker可将应用程序和基础设施层隔离,并且能将基础设施当作程序一样进行管理。使用Docker,可更快地打包、测试以及部署应用程序,并可减少从编写到部署运行代码的周期。
版本
Docker目前主要分免费的社区版和收费的企业版:
- Docker CE(Docker Community Edition):包含了Docker原生的大部分功能,可以满足多数企业的功能性需求。
- Docker EE(Docker Enterprise Edition):除了社区版的功能外,追加了具有集中管理功能的Docker Datacenter和大量的安全增强组件,适合对于管控和安全有较高要求的公司。
Docker架构
看下来自Docker官方文档的架构图:

下面讲解图中包含的组件:
(1) Docker daemon(Docker守护进程)
Docker daemon是一个运行在宿主机(DOCKER_HOST)的后台进程。我们可通过Docker客户端与之通信。
(2) Client(Docker客户端)
Docker客户端是Docker的用户界面,它可以接受用户命令和配置标识,并与Docker daemon通信。图中,docker build等都是Docker的相关命令。
(3) Images(Docker镜像)
Docker镜像是一个只读模板,它包含创建Docker容器的说明。它和系统安装光盘有点像——我们使用系统安装光盘安装系统,同理,我们使用Docker镜像运行Docker镜像中的程序。
(4) Container(容器)
容器是镜像的可运行实例。镜像和容器的关系有点类似于面向对象中,类和对象的关系。我们可通过Docker API或者CLI命令来启停、移动、删除容器。
(5) Registry
Docker Registry是一个集中存储与分发镜像的服务。我们构建完Docker镜像后,就可在当前宿主机上运行。但如果想要在其他机器上运行这个镜像,我们就需要手动拷贝。此时,我们可借助Docker Registry来避免镜像的手动拷贝。
一个Docker Registry可包含多个Docker仓库;每个仓库可包含多个镜像标签;每个标签对应一个Docker镜像。这跟Maven的仓库有点类似,如果把Docker Registry比作Maven仓库的话,那么Docker仓库就可理解为某jar包的路径,而镜像标签则可理解为jar包的版本号。
Docker Registry可分为公有Docker Registry和私有Docker Registry。最常用的Docker Registry莫过于官方的Docker Hub,这也是默认的Docker Registry。Docker Hub上存放着大量优秀的镜像,我们可使用Docker命令下载并使用。
Docker的常用命令
image镜像相关
1、下载镜像
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
| Name, shorthand | Default | Description |
|---|---|---|
| --all-tags, -a | false | 下载所有标签的镜像 |
| --disable-content-trust | true | 忽略镜像的校验 |
例:
docker pull java:8
执行该命令后,Docker会从Docker Hub中的java仓库下载最新版本的Java镜像。
2、列出镜像
docker images
执行命令后,会看到如下的表格:

表格列含义:
① REPOSITORY:镜像所属仓库名称。
② TAG:镜像标签。默认是latest,表示最新。
③ IMAGE ID:镜像ID,表示镜像唯一标识。
④ CREATED:镜像创建时间。
⑤ SIZE:镜像大小。
3、删除镜像
docker rmi [OPTIONS] IMAGE [IMAGE...]
| Name, shorthand | Default | Description |
|---|---|---|
| --force, -f | false | 强制删除 |
| --no-prune | false | 不移除该镜像的过程镜像,默认移除 |
例:
docker rmi hello-world
4、构建镜像
通过Dockerfile构建镜像。
docker build [OPTIONS] PATH | URL | -
| Name, shorthand | Default | Description |
|---|---|---|
| --add-host | 添加自定义从host到IP的映射,格式为(host:ip) | |
| --build-arg | 设置构建时的变量 | |
| --cache-from | 作为缓存源的镜像 | |
| --cgroup-parent | 容器可选的父cgroup | |
| --compress | false | 使用gzip压缩构建上下文 |
| --cpu-period | 0 | 限制CPU CFS (Completely Fair Scheduler) 周期 |
| --cpu-quota | 0 | 限制CPU CFS (Completely Fair Scheduler) 配额 |
| --cpu-shares, -c | 0 | CPU使用权重(相对权重) |
| --cpuset-cpus | 指定允许执行的CPU | |
| --cpuset-mems | 指定允许执行的内存 | |
| --disable-content-trust | true | 忽略校验 |
| --file, -f | 指定Dockerfile的名称,默认是‘PATH/Dockerfile’ | |
| --force-rm | false | 删除中间容器 |
| --iidfile | 将镜像ID写到文件中 | |
| --isolation | 容器隔离技术 | |
| --label | 设置镜像使用的元数据 | |
| --memory, -m | 0 | 设置内存限制 |
| --memory-swap | 0 | 设置Swap的最大值为内存+swap,如果设置为-1表示不限swap |
| --network | default | 在构建期间设置RUN指令的网络模式 |
| --no-cache | false | 构建镜像过程中不使用缓存 |
| --pull | false | 总是尝试去更新镜像的新版本 |
| --quiet, -q | false | 静默模式,构建成功后只输出镜像ID |
| --rm | true | 构建成功后立即删除中间容器 |
| --security-opt | 安全选项 | |
| --shm-size | 0 | 指定/dev/shm 目录的大小 |
| --squash | false | 将构建的层压缩成一个新的层 |
| --tag, -t | 设置标签,格式:name:tag,tag可选 | |
| --target | 设置构建时的目标构建阶段 | |
| --ulimit | Ulimit 选项 |
例:
docker build -t mysh .
Container容器相关
容器生命周期

1、新建并启动容器
docker run
该命令可以新建并启动一个容器,是我们最常用的命令了,它还有很多选项:
- -d选项:表示后台运行
- -P选项:随机端口映射
- -p选项:指定端口映射,有以下四种格式。
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort - –network选项:指定网络模式,该选项有以下可选参数:
–network=bridge: 默认选项,表示连接到默认的网桥。
–network=host:容器使用宿主机的网络。
–network=container:NAME_or_ID:告诉Docker让新建的容器使用已有容器的网络配置。
–network=none:不配置该容器的网络,用户可自定义网络配置。
例:
docker run -d -p 91:80 nginx
启动一个Nginx容器,并在后台运行,开放容器端口80到宿主机端口91。浏览器访问容器nginx:http://localhost:91
注意:使用docker run命令创建容器时,会先检查本地是否存在指定镜像。如果本地不存在该名称的镜像,Docker就会自动从Docker Hub下载镜像并启动一个Docker容器。
2、列出容器
docker ps [OPTIONS]
| Name, shorthand | Default | Description |
|---|---|---|
| --all, -a | false | 列出所有容器,包括未运行的容器,默认只展示运行的容器 |
| --filter, -f | 根据条件过滤显示内容 | |
| --format | 通过Go语言模板文件展示镜像 | |
| --last, -n | -1 | 显示最近创建n个容器(包含所有状态) |
| --latest, -l | false | 显示最近创建的容器(包含所有状态) |
| --no-trunc | false | 不截断输出 |
| --quiet, -q | false | 静默模式,只展示容器的编号 |
| --size, -s | false | 显示总文件大小 |
执行该命令后,可看到类似于如下的表格:

该表格列含义:
① CONTAINER_ID:表示容器ID。
② IMAGE:表示镜像名称。
③ COMMAND:表示启动容器时运行的命令。
④ CREATED:表示容器的创建时间。
⑤ STATUS:表示容器运行的状态。Up表示运行中,Exited表示已停止。
⑥ PORTS:表示容器对外的端口号。
⑦ NAMES:表示容器名称。该名称默认由Docker自动生成,也可使用docker run命令的–name选项自行指定。
例:
docker ps -n 5
docker ps -a
3、停止容器
docker stop [OPTIONS] CONTAINER [CONTAINER...]
| Name, shorthand | Default | Description |
|---|---|---|
| --time, -t | 10 | 强制杀死容器前等待的时间,单位是秒 |
例:
docker stop 784fd3b294d7
其中784fd3b294d7 是容器ID,当然也可使用docker stop 容器名称 来停止指定容器。
4、强制停止容器
docker kill [OPTIONS] CONTAINER [CONTAINER...]
| Name, shorthand | Default | Description |
|---|---|---|
| --signal, -s | KILL | 向容器发送一个信号 |
例:
docker kill 784fd3b294d7
5、启动已停止的容器
docker start [OPTIONS] CONTAINER [CONTAINER...]
| Name, shorthand | Default | Description |
|---|---|---|
| --attach, -a | false | 连接STDOUT/STDERR并转发信号 |
| --checkpoint | 从该检查点还原 | |
| --checkpoint-dir | 使用自定义的检查点存储目录 | |
| --detach-keys | 覆盖断开容器的关键顺序 | |
| --interactive, -i | false | 连接容器的STDIN |
例:
docker start 784fd3b294d7
6、重启容器
docker restart [OPTIONS] CONTAINER [CONTAINER...]
| Name, shorthand | Default | Description |
|---|---|---|
| --time, -t | 10 | 关闭容器前等待的时间,单位是秒 |
7、进入容器
某场景下,我们可能需要进入运行中的容器,我们可以通过一下方式进入容器:
-
①使用docker attach 命令进入容器。
例如:docker attach 784fd3b294d7很多场景下,使用docker attach 命令并不方便。当多个窗口同时attach到同一个容器时,所有窗口都会同步显示。同理,如果某个窗口发生阻塞,其他窗口也无法执行操作。
-
② 使用nsenter 进入容器
nsenter工具包含在util-linux 2.23或更高版本中。为了连接到容器,我们需要找到容器第一个进程的PID,可通过以下命令获取:docker inspect --format "{{.State.Pid}}" $CONTAINER_ID获得PID后,就可使用nsenter命令进入容器了:
nsenter --target "$PID" --mount --uts --ipc --net --pid下面给出一个完整的例子:
[root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 784fd3b294d7 nginx "nginx -g 'daemon off" 55 minutes ago Up 3 minutes 443/tcp, 0.0.0.0:91->80/tcp backstabbing_archimedes [root@localhost ~]# docker inspect --format "{{.State.Pid}}" 784fd3b294d7 95492 [root@localhost ~]# nsenter --target 95492 --mount --uts --ipc --net --pid root@784fd3b294d7:/#也可将以上两条命令封装成一个Shell,从而简化进入容器的过程。
-
③ docker exec
docker exec -it 容器id /bin/bash
8、删除容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]
| Name, shorthand | Default | Description |
|---|---|---|
| --force, -f | false | 通过SIGKILL信号强制删除正在运行中的容器 |
| --link, -l | false | 删除容器间的网络连接 |
| --volumes, -v | false | 删除与容器关联的卷 |
例1:删除指定容器
docker rm 784fd3b294d7
该命令只能删除已停止的容器,如需删除正在运行的容器,可使用-f参数。
例2:删除所有的容器。
docker rm -f $(docker ps -a -q)
Dockerfile打包镜像
Dockerfile指令
FROM
使用FROM指令指定基础镜像,FROM指令有点像Java里面的“extends”关键字。需要注意的是,FROM指令必须指定且需要写在其他指令之前。FROM指令后的所有指令都依赖于该指令所指定的镜像。
支持三种格式:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
ADD
ADD指令用于复制文件,格式为:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
从src目录复制文件到容器的dest。其中src可以是Dockerfile所在目录的相对路径,也可以是一个URL,还可以是一个压缩包
注意:
① src必须在构建的上下文内,不能使用例如:ADD ../somethine /something 这样的命令,因为docker build 命令首先会将上下文路径和其子目录发送到docker daemon。
② 如果src是一个URL,同时dest不以斜杠结尾,dest将会被视为文件,src对应内容文件将会被下载到dest。
③ 如果src是一个URL,同时dest以斜杠结尾,dest将被视为目录,src对应内容将会被下载到dest目录。
④ 如果src是一个目录,那么整个目录下的内容将会被拷贝,包括文件系统元数据。
⑤ 如果文件是可识别的压缩包格式,则docker会自动解压。
示例:
ADD test4.tar.gz .
复制test4.tar.gz压缩包到容器的根目录,并会被自动解压。
RUN
该指令支持两种格式:
RUN <command>
RUN ["executable", "param1", "param2"]
RUN <command> 在shell终端中运行,在Linux中默认是/bin/sh -c ,在Windows中是cmd /s /c,使用这种格式,就像直接在命令行中输入命令一样。
RUN ["executable", "param1", "param2"] 使用exec执行,这种方式类似于函数调用。指定其他终端可以通过该方式操作,例如:RUN ["/bin/bash", "-c", "echo hello"] ,该方式必须使用双引号[“]而不能使用单引号[‘],因为该方式会被转换成一个JSON 数组。
例:
RUN mkdir test1
COPY
复制文件,格式为:
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
复制本地端的src到容器的dest。COPY指令和ADD指令类似,COPY不支持URL和压缩包。
ENTRYPOINT
格式为:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT和CMD指令的目的一样,都是指定Docker容器启动时执行的命令,可多次设置,但只有最后一个有效。ENTRYPOINT不可被重写覆盖。
例:
ENTRYPOINT ["java","-jar","app.jar"]
CMD
CMD指令用于为执行容器提供默认值。每个Dockerfile只有一个CMD命令,如果指定了多个CMD命令,那么只有最后一条会被执行,如果启动容器的时候指定了运行的命令,则会覆盖掉CMD指定的命令。
支持三种格式:
CMD ["executable","param1","param2"] (推荐使用)
CMD ["param1","param2"] (为ENTRYPOINT指令提供预设参数)
CMD command param1 param2 (在shell中执行)
ENV
ENV指令用于设置环境变量,格式为:
ENV <key> <value>
ENV <key>=<value> ...
示例:
ENV JAVA_HOME /path/to/java
ARG
ARG指令用于设置构建参数,类似于ENV。和ARG不同的是,ARG设置的是构建时的环境变量,在容器运行时是不会存在这些变量的。
格式为:
ARG <name>[=<default value>]
示例:
ARG user1=someuser
VOLUME
该指令使容器中的一个目录具有持久化存储的功能,该目录可被容器本身使用,也可共享给其他容器。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。格式为:
VOLUME ["/data"]
例:
FROM nginx
VOLUME /tmp
当该Dockerfile被构建成镜像后,/tmp目录中的数据即使容器关闭也依然存在。如果另一个容器也有持久化的需求,并且想使用以上容器/tmp目录中的内容,则可使用如下命令启动容器:
docker run -volume-from 容器ID 镜像名称 # 容器ID是di一个容器的ID,镜像是第二个容器所使用的镜像。
Dockerfile打包一个 springboot 应用镜像
新建Dockerfile文件:
vim Dockerfile
输入内容:
# 基于哪个镜像
FROM java:8
# 将本地文件夹挂载到当前容器
VOLUME /tmp
# 拷贝文件到容器
ADD config-server.jar config-server.jar'
# 配置容器启动后执行的命令
ENTRYPOINT ["java","-jar","config-server.jar"]
保存文件后,输入以下命令打包镜像:
docker build -t myConfigServer
打包成功后启动镜像到容器里:
docker run -p 8080:8080 --name myConfigServer myConfigServer
其中--name myConfigServer是指定容器的名称,最后一个myConfigServer是指定镜像名。

浙公网安备 33010602011771号