Docker学习笔记

logo-docker

Docker学习笔记

Docker架构

Docker 包括三个基本概念:

  • 镜像(Image): Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。

  • 容器(Container): 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

  • 仓库(Repository): 仓库可看成一个代码控制中心,用来保存镜像。

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。

Docker 容器通过 Docker 镜像来创建。

容器与镜像的关系类似于面向对象编程中的对象与类。

Docker 面向对象
容器 对象
镜像

docker-framework

概念 说明
Docker 镜像(Images) Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。
Docker 容器(Container) 容器是独立运行的一个或一组应用,是镜像运行时的实体。
Docker 客户端(Client) Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
Docker 主机(Host) 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker Registry Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
Docker Machine Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。

Docker 安装

Centos Docker 安装

  1. 卸载旧版本

    旧版本的 Docker 被称为 dockerdocker-engine 。如果安装了这些,请卸载它们以及相关的依赖项。

    1
    2
    3
    4
    5
    6
    7
    8
    ] yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine
  2. 下载docker-ce.repo

    1
    ] wget https://download.docker.com/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
  3. 使用yum命令安装docker

    1
    ] yum install docker-ce docker-ce-cli containerd.io
  4. 启动docker

    1
    2
    ] systemctl start docker
    ] systemctl enable docker
  5. ​ 验证

    1
    2
    ] docker --version
    Docker version 20.10.12, build e91ed57

Docker 镜像加速

Docker cn:https://registry.docker-cn.com
阿里云镜像仓库:https://<你的ID>.mirror.aliyuncs.com
中国科技大学:https://docker.mirrors.ustc.edu.cn/
网易:https://hub-mirror.c.163.com/

编辑daemon.json 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
] vim /etc/docker/daemon.json
] cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://<你的ID>.mirror.aliyuncs.com","https://docker.mirrors.ustc.edu.cn/","https://hub-mirror.c.163.com/"]
}

] systemctl restart docker # 重启docker使镜像加速生效
] docker info # 查看加速是否生效
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Build with BuildKit (Docker Inc., v0.6.1-docker)
scan: Docker Scan (Docker Inc., v0.8.0)
......
Registry Mirrors:
https://<你的ID>.mirror.aliyuncs.com/
https://docker.mirrors.ustc.edu.cn/
https://hub-mirror.c.163.com/
Live Restore Enabled: false

Docker 配置文件

配置文件 文件名称
环境配置文件 /etc/sysconfig/docker-network
/etc/sysconfig/docker-storage
/etc/sysconfig/docker
Unit File /usr/lib/systemd/system/docker.service
Docker Registry配置文件 /etc/containers/registries.conf
docker-ce配置文件 /etc/docker/daemon.json

Docker 常用命令

简单介绍

命令 描述 实例
容器生命周期管理
run docker run:创建一个新的容器并运行一个命令 docker run –name mynginx -d nginx:latest
start/stop/restart docker start:启动一个或多个已经被停止的容器
docker stop:停止一个运行中的容器
docker restart:重启容器
docker restart myrunoob
docker start myrunoob
docker restart myunoob
kill docker kill:杀掉一个运行中的容器。 docker kill -s KILL mynginx
rm docker rm: 删除一个或多个容器。 docker rm -f db01 db02
pause/unpause docker pause:暂停容器中所有的进程。
docker unpause:恢复容器中所有的进程。
docker pause db01
docker unpause db01
create docker create:创建一个新的容器但不启动它 docker create –name myrunoob nginx:latest
exec docker exec:在运行的容器中执行命令 docker exec -it mynginx /bin/sh /root/runoob.sh
容器操作
ps docker ps:列出容器 docker ps
inspect docker inspect:获取容器/镜像的元数据。 docker inspect mysql:5.6
top docker top:看容器中运行的进程信息,支持 ps 命令参数。 docker top mymysql
attach docker attach:接到正在运行中的容器。 docker attach –sig-proxy=false mynginx
events docker events:从服务器获取实时事件 docker events –since=”1467302400”
logs docker logs:获取容器的日志 docker logs -f mynginx
wait docker wait:阻塞运行直到容器停止,然后打印出它的退出代码。 docker wait CONTAINER
export docker export:将文件系统作为一个tar归档文件导出到STDOUT。 docker export -o mysql-`date +%Y%m%d`.tar a404c6c174a2
port docker port:列出指定的容器的端口映射,或者查找将PRIVATE_PORT NAT到面向公众的端口。 docker port mymysql
容器rootfs命令
commit docker commit:从容器创建一个新的镜像。 docker commit -a “runoob.com” -m “my apache” a404c6c174a2 mymysql:v1
cp docker cp:用于容器与主机之间的数据拷贝。 docker cp /www/runoob 96f7f14e99ab:/www/
diff docker diff:检查容器里文件结构的更改。 docker diff mymysql
镜像仓库
login/logout docker login:登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker logout: 登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker login -u sample-user -p sample-password
docker logout
pull docker pull:从镜像仓库中拉取或者更新指定镜像 docker pull java
push docker push:将本地的镜像上传到镜像仓库,要先登陆到镜像仓库 docker push myapache:v1
search docker search:从Docker Hub查找镜像 docker search -f stars=10 java
本地镜像管理
images docker images:列出本地镜像。 docker images
rmi docker rmi:删除本地一个或多个镜像。 docker rmi imagesID
tag docker tag:标记本地镜像,将其归入某一仓库。 docker tag ubuntu:15.10 runoob/ubuntu:v3
build docker build:命令用于使用 Dockerfile 创建镜像。 docker build -t runoob/ubuntu:v1 .
history docker history:查看指定镜像的创建历史。 docker history runoob/ubuntu:v3
save docker save:将指定镜像保存成 tar 归档文件。 docker save -o my_ubuntu_v3.tar runoob/ubuntu:v3
load docker load:导入使用 docker save 命令导出的镜像。 docker load < busybox.tar.gz
import docker import:从归档文件中创建镜像。 docker import my_ubuntu_v3.tar runoob/ubuntu:v4
info/version
info docker info:显示 Docker 系统信息,包括镜像和容器数。 docker info
version docker version:显示 Docker 版本信息。 docker version
Docker Manager
network docker network:管理docker网络命令 docker network ls
volumes docker volumes:管理docker存储卷命令

容器生命周期管理

run

docker run: 创建一个新的容器并运行一个命令

语法

1
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS说明:

  • -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -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=[]: 开放一个端口或一组端口;
  • –volume , -v: 绑定一个卷
  • –restart: 设置开机启动,no:默认策略,在容器退出时不重启容器;on-failure:在容器非正常退出时(退出状态非0),才会重启容器;on-failure:3:在容器非正常退出时重启容器,最多重启3次;always:在容器退出时总是重启容器;unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器

实例

使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。

1
docker run --name mynginx -d nginx:latest

使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。

1
docker run -P -d nginx:latest

使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。

1
docker run -p 80:80 -v /data:/data -d nginx:latest

绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.1 的 80 端口上。

1
$ docker run -p 127.0.0.1:80:8080/tcp ubuntu bash

使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。

1
2
runoob@runoob:~$ docker run -it nginx:latest /bin/bash
root@b8573233d675:/#

start/stop/restart

docker start:启动一个或多个已经被停止的容器

docker stop:停止一个运行中的容器

docker restart:重启容器

语法

1
2
3
docker start [OPTIONS] CONTAINER [CONTAINER...]
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker restart [OPTIONS] CONTAINER [CONTAINER...]

实例

启动已被停止的容器myrunoob

1
docker start myrunoob

停止运行中的容器myrunoob

1
docker stop myrunoob

重启容器myrunoob

1
docker restart myrunoob

kill

docker kill:杀掉一个运行中的容器。

语法

1
docker kill [OPTIONS] CONTAINER [CONTAINER...]

OPTIONS说明:

  • -s: 向容器发送一个信号

实例

杀掉运行中的容器mynginx

1
2
runoob@runoob:~$ docker kill -s KILL mynginx
mynginx

rm

docker rm: 删除一个或多个容器。

语法

1
docker rm [OPTIONS] CONTAINER [CONTAINER...]

OPTIONS说明:

  • -f: 通过 SIGKILL 信号强制删除一个运行中的容器。
  • -l: 移除容器间的网络连接,而非容器本身。
  • -v: 删除与容器关联的卷。

实例

强制删除容器 db01、db02:

1
docker rm -f db01 db02

移除容器 nginx01 对容器 db01 的连接,连接名 db:

1
docker rm -l db 

删除容器 nginx01, 并删除容器挂载的数据卷:

1
docker rm -v nginx01

删除所有已经停止的容器:

1
docker rm $(docker ps -a -q)

pause/unpause

docker pause:暂停容器中所有的进程。

docker unpause:恢复容器中所有的进程。

语法

1
2
docker pause CONTAINER [CONTAINER...]
docker unpause CONTAINER [CONTAINER...]

实例

暂停数据库容器db01提供服务。

1
docker pause db01

恢复数据库容器 db01 提供服务。

1
docker unpause db01

create

docker create: 创建一个新的容器但不启动它

用法同 docker run

语法

1
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]

语法同 docker run

实例

使用docker镜像nginx:latest创建一个容器,并将容器命名为myrunoob

1
2
runoob@runoob:~$ docker create  --name myrunoob  nginx:latest
09b93464c2f75b7b69f83d56a9cfc23ceb50a48a9db7652ee4c27e3e2cb1961f

exec

docker exec: 在运行的容器中执行命令

语法

1
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

OPTIONS说明:

  • -d: 分离模式: 在后台运行
  • -i: 即使没有附加也保持STDIN 打开
  • -t: 分配一个伪终端

实例

在容器 mynginx 中以交互模式执行容器内 /root/runoob.sh 脚本:

1
2
runoob@runoob:~$ docker exec -it mynginx /bin/sh /root/runoob.sh
http://www.runoob.com/

在容器 mynginx 中开启一个交互模式的终端:

1
2
runoob@runoob:~$ docker exec -i -t  mynginx /bin/bash
root@b1a0703e41e7:/#

也可以通过 docker ps -a 命令查看已经在运行的容器,然后使用容器 ID 进入容器。

查看已经在运行的容器 ID:

1
2
3
4
# docker ps -a 
...
9df70f9a0714 openjdk "/usercode/script.sh…"
...

第一列的 9df70f9a0714 就是容器 ID。

通过 exec 命令对指定的容器执行 bash:

1
# docker exec -it 9df70f9a0714 /bin/bash

容器操作

ps

docker ps: 列出容器

语法

1
docker ps [OPTIONS]

OPTIONS说明:

  • -a: 显示所有的容器,包括未运行的。
  • -f: 根据条件过滤显示的内容。
  • –format: 指定返回值的模板文件。
  • -l: 显示最近创建的容器。
  • -n: 列出最近创建的n个容器。
  • –no-trunc: 不截断输出。
  • -q: 静默模式,只显示容器编号。
  • -s: 显示总的文件大小。

实例

列出所有在运行的容器信息。

1
2
3
4
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
09b93464c2f7 nginx:latest "nginx -g 'daemon off" ... 80/tcp, 443/tcp myrunoob
96f7f14e99ab mysql:5.6 "docker-entrypoint.sh" ... 0.0.0.03306->3306/tcp mymysql

输出详情介绍:

CONTAINER ID: 容器 ID。

IMAGE: 使用的镜像。

COMMAND: 启动容器时运行的命令。

CREATED: 容器的创建时间。

STATUS: 容器状态。

状态有7种:

  • created(已创建)
  • restarting(重启中)
  • running(运行中)
  • removing(迁移中)
  • paused(暂停)
  • exited(停止)
  • dead(死亡)

PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。

NAMES: 自动分配的容器名称。

列出最近创建的5个容器信息。

1
2
3
4
5
6
7
runoob@runoob:~$ docker ps -n 5
CONTAINER ID IMAGE COMMAND CREATED
09b93464c2f7 nginx:latest "nginx -g 'daemon off" 2 days ago ...
b8573233d675 nginx:latest "/bin/bash" 2 days ago ...
b1a0703e41e7 nginx:latest "nginx -g 'daemon off" 2 days ago ...
f46fb1dec520 5c6e1090e771 "/bin/sh -c 'set -x \t" 2 days ago ...
a63b4a5597de 860c279d2fec "bash" 2 days ago ...

列出所有创建的容器ID。

1
2
3
4
5
6
7
8
9
10
11
12
runoob@runoob:~$ docker ps -a -q
09b93464c2f7
b8573233d675
b1a0703e41e7
f46fb1dec520
a63b4a5597de
6a4aa42e947b
de7bb36e7968
43a432b73776
664a8ab1a585
ba52eb632bbd
...

inspect

docker inspect: 获取容器/镜像的元数据。

语法

1
docker inspect [OPTIONS] NAME|ID [NAME|ID...]

OPTIONS说明:

  • -f: 指定返回值的模板文件。
  • -s: 显示总的文件大小。
  • –type: 为指定类型返回JSON。

实例

获取镜像mysql:5.6的元信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
runoob@runoob:~$ docker inspect mysql:5.6
[
{
"Id""sha256:2c0964ec182ae9a045f866bbc2553087f6e42bfc16074a74fb820af235f070ec",
"RepoTags": [
"mysql:5.6"
],
"RepoDigests": [],
"Parent""",
"Comment""",
"Created""2016-05-24T04:01:41.168371815Z",
"Container""e0924bc460ff97787f34610115e9363e6363b30b8efa406e28eb495ab199ca54",
"ContainerConfig": {
"Hostname""b0cf605c7757",
"Domainname""",
"User""",
"AttachStdin"false,
"AttachStdout"false,
"AttachStderr"false,
"ExposedPorts": {
"3306/tcp": {}
},
...

获取正在运行的容器mymysql的 IP。

1
2
runoob@runoob:~$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mymysql
172.17.0.3

top

docker top: 查看容器中运行的进程信息,支持 ps 命令参数。

语法

1
docker top [OPTIONS] CONTAINER [ps OPTIONS]

容器运行时不一定有/bin/bash终端来交互执行top命令,而且容器还不一定有top命令,可以使用docker top来实现查看container中正在运行的进程。

实例

查看容器mymysql的进程信息。

1
2
3
runoob@runoob:~/mysql$ docker top mymysql
UID PID PPID C STIME TTY TIME CMD
999 40347 40331 18 0058 ? 000002 mysqld

查看所有运行容器的进程信息。

1
for i in  `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i; done

attach

docker attach: 连接到正在运行中的容器。

语法

1
docker attach [OPTIONS] CONTAINER

要attach上去的容器必须正在运行,可以同时连接上同一个container来共享屏幕(与screen命令的attach类似)。

官方文档中说attach后可以通过CTRL-C来detach,但实际上经过我的测试,如果container当前在运行bash,CTRL-C自然是当前行的输入,没有退出;如果container当前正在前台运行进程,如输出nginx的access.log日志,CTRL-C不仅会导致退出容器,而且还stop了。这不是我们想要的,detach的意思按理应该是脱离容器终端,但容器依然运行。好在attach是可以带上–sig-proxy=false来确保CTRL-D或CTRL-C不会关闭容器。

实例

容器mynginx将访问日志指到标准输出,连接到容器查看访问信息。

1
2
runoob@runoob:~$ docker attach --sig-proxy=false mynginx
192.168.239.1 - - [10/Jul/2016:16:54:26 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"

events

docker events: 从服务器获取实时事件

语法

1
docker events [OPTIONS]

OPTIONS说明:

  • -f: 根据条件过滤事件;
  • –since: 从指定的时间戳后显示所有事件;
  • –until: 流水时间显示到指定的时间为止;

实例

显示docker 2016年7月1日后的所有事件。

1
2
3
4
5
6
runoob@runoob:~/mysql$ docker events  --since="1467302400"
2016-07-08T19:44:54.501277677+08:00 network connect 66f958fd13dc4314ad20034e576d5c5eba72e0849dcc38ad9e8436314a4149d4 (container=b8573233d675705df8c89796a2c2687cd8e36e03646457a15fb51022db440e64, name=bridge, type=bridge)
2016-07-08T19:44:54.723876221+08:00 container start b8573233d675705df8c89796a2c2687cd8e36e03646457a15fb51022db440e64 (image=nginx:latest, name=elegant_albattani)
2016-07-08T19:44:54.726110498+08:00 container resize b8573233d675705df8c89796a2c2687cd8e36e03646457a15fb51022db440e64 (height=39, image=nginx:latest, name=elegant_albattani, width=167)
2016-07-08T19:46:22.137250899+08:00 container die b8573233d675705df8c89796a2c2687cd8e36e03646457a15fb51022db440e64 (exitCode=0, image=nginx:latest, name=elegant_albattani)
...

显示docker 镜像为mysql:5.6 2016年7月1日后的相关事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
runoob@runoob:~/mysql$ docker events -f "image"="mysql:5.6" --since="1467302400" 
2016-07-11T00:3853.975174837+0800 container start 96f7f14e99ab9d2f60943a50be23035eda1623782cc5f930411bbea407a2bb10 (image=mysql:5.6, name=mymysql)
2016-07-11T00:5117.022572452+0800 container kill 96f7f14e99ab9d2f60943a50be23035eda1623782cc5f930411bbea407a2bb10 (image=mysql:5.6, name=mymysql, signal=9)
2016-07-11T00:5117.132532080+0800 container die 96f7f14e99ab9d2f60943a50be23035eda1623782cc5f930411bbea407a2bb10 (exitCode=137, image=mysql:5.6, name=mymysql)
2016-07-11T00:5117.514661357+0800 container destroy 96f7f14e99ab9d2f60943a50be23035eda1623782cc5f930411bbea407a2bb10 (image=mysql:5.6, name=mymysql)
2016-07-11T00:5718.551984549+0800 container create c8f0a32f12f5ec061d286af0b1285601a3e33a90a08ff1706de619ac823c345c (image=mysql:5.6, name=mymysql)
2016-07-11T00:5718.557405864+0800 container attach c8f0a32f12f5ec061d286af0b1285601a3e33a90a08ff1706de619ac823c345c (image=mysql:5.6, name=mymysql)
2016-07-11T00:5718.844134112+0800 container start c8f0a32f12f5ec061d286af0b1285601a3e33a90a08ff1706de619ac823c345c (image=mysql:5.6, name=mymysql)
2016-07-11T00:5719.140141428+0800 container die c8f0a32f12f5ec061d286af0b1285601a3e33a90a08ff1706de619ac823c345c (exitCode=1, image=mysql:5.6, name=mymysql)
2016-07-11T00:5805.941019136+0800 container destroy c8f0a32f12f5ec061d286af0b1285601a3e33a90a08ff1706de619ac823c345c (image=mysql:5.6, name=mymysql)
2016-07-11T00:5807.965128417+0800 container create a404c6c174a21c52f199cfce476e041074ab020453c7df2a13a7869b48f2f37e (image=mysql:5.6, name=mymysql)
2016-07-11T00:5808.188734598+0800 container start a404c6c174a21c52f199cfce476e041074ab020453c7df2a13a7869b48f2f37e (image=mysql:5.6, name=mymysql)
2016-07-11T00:5820.010876777+0800 container top a404c6c174a21c52f199cfce476e041074ab020453c7df2a13a7869b48f2f37e (image=mysql:5.6, name=mymysql)
2016-07-11T01:0601.395365098+0800 container top a404c6c174a21c52f199cfce476e041074ab020453c7df2a13a7869b48f2f37e (image=mysql:5.6, name=mymysql)

如果指定的时间是到秒级的,需要将时间转成时间戳。如果时间为日期的话,可以直接使用,如–since=”2016-07-01”。

logs

docker logs: 获取容器的日志

语法

1
docker logs [OPTIONS] CONTAINER

OPTIONS说明:

  • -f: 跟踪日志输出
  • –since: 显示某个开始时间的所有日志
  • -t: 显示时间戳
  • –tail: 仅列出最新N条容器日志

实例

跟踪查看容器mynginx的日志输出。

1
2
3
4
5
6
runoob@runoob:~$ docker logs -f mynginx
192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
2016/07/10 165333 [error] 5#5: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.239.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.239.130", referrer: "http://192.168.239.130/"
192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://192.168.239.130/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
192.168.239.1 - - [10/Jul/2016:16:53:59 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
...

查看容器mynginx从2016年7月1日后的最新10条日志。

1
docker logs --since="2016-07-01" --tail=10 mynginx

wait

docker wait: 阻塞运行直到容器停止,然后打印出它的退出代码。

语法

1
docker wait [OPTIONS] CONTAINER [CONTAINER...]

实例

1
docker wait CONTAINER

export

docker export: 将文件系统作为一个tar归档文件导出到STDOUT。

语法

1
docker export [OPTIONS] CONTAINER

OPTIONS说明:

  • -o: 将输入内容写到文件。

实例

将id为a404c6c174a2的容器按日期保存为tar文件。

1
2
3
runoob@runoob:~$ docker export -o mysql-`date +%Y%m%d`.tar a404c6c174a2
runoob@runoob:~$ ls mysql-`date +%Y%m%d`.tar
mysql-20160711.tar

port

docker port: 列出指定的容器的端口映射,或者查找将PRIVATE_PORT NAT到面向公众的端口。

语法

1
docker port [OPTIONS] CONTAINER [PRIVATE_PORT[/PROTO]]

实例

查看容器mynginx的端口映射情况。

1
2
runoob@runoob:~$ docker port mymysql
3306/tcp -> 0.0.0.03306

容器rootfs命令

commit

docker commit: 从容器创建一个新的镜像。

语法

1
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS说明:

  • -a: 提交的镜像作者;
  • -c: 使用Dockerfile指令来创建镜像;
  • -m: 提交时的说明文字;
  • -p: 在commit时,将容器暂停。

实例

将容器a404c6c174a2 保存为新的镜像,并添加提交人信息和说明信息。

1
2
3
4
5
runoob@runoob:~$ docker commit -a "runoob.com" -m "my apache" a404c6c174a2  mymysql:v1 
sha25637af1236adef1544e8886be23010b66577647a40bc02c0885a6600b33ee28057
runoob@runoob:~$ docker images mymysql:v1
REPOSITORY TAG IMAGE ID CREATED SIZE
mymysql v1 37af1236adef 15 seconds ago 329 MB

cp

docker cp: 用于容器与主机之间的数据拷贝。

语法

1
2
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

OPTIONS说明:

  • -L: 保持源目标中的链接

实例

将主机/www/runoob目录拷贝到容器96f7f14e99ab的/www目录下。

1
docker cp /www/runoob 96f7f14e99ab:/www/

将主机/www/runoob目录拷贝到容器96f7f14e99ab中,目录重命名为www。

1
docker cp /www/runoob 96f7f14e99ab:/www

将容器96f7f14e99ab的/www目录拷贝到主机的/tmp目录中。

1
docker cp  96f7f14e99ab:/www /tmp/

diff

docker diff: 检查容器里文件结构的更改。

语法

1
docker diff [OPTIONS] CONTAINER

实例

查看容器mymysql的文件结构更改。

1
2
3
4
5
6
7
8
runoob@runoob:~$ docker diff mymysql
A /logs
A /mysql_data
C /run
C /run/mysqld
A /run/mysqld/mysqld.pid
A /run/mysqld/mysqld.sock
C /tmp

镜像仓库

login/logout

docker login: 登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub

docker logout: 登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub

语法

1
2
docker login [OPTIONS] [SERVER]
docker logout [OPTIONS] [SERVER]

OPTIONS说明:

  • -u:登陆的用户名
  • -p:登陆的密码

实例

登陆到Docker Hub

1
docker login -u 用户名 -p 密码

登出Docker Hub

1
docker logout

pull

docker pull: 从镜像仓库中拉取或者更新指定镜像

语法

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

OPTIONS说明:

  • -a: 拉取所有 tagged 镜像

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

实例

从Docker Hub下载java最新版镜像。

1
docker pull java

从Docker Hub下载REPOSITORY为java的所有镜像。

1
docker pull -a java

push

docker push: 将本地的镜像上传到镜像仓库,要先登陆到镜像仓库

语法

1
docker push [OPTIONS] NAME[:TAG]

OPTIONS说明:

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

实例

上传本地镜像myapache:v1到镜像仓库中。

1
docker push myapache:v1

docker search: 从Docker Hub查找镜像

语法

1
docker search [OPTIONS] TERM

OPTIONS说明:

  • –automated: 只列出 automated build类型的镜像;
  • –no-trunc: 显示完整的镜像描述;
  • -f <过滤条件>: 列出收藏数不小于指定值的镜像。

实例

从 Docker Hub 查找所有镜像名包含 java,并且收藏数大于 10 的镜像

1
2
3
4
5
6
7
8
runoob@runoob:~$ docker search -f stars=10 java
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
java Java is a concurrent, class-based... 1037 [OK]
anapsix/alpine-java Oracle Java 8 (and 7) with GLIBC ... 115 [OK]
develar/java 46 [OK]
isuper/java-oracle This repository contains all java... 38 [OK]
lwieske/java-8 Oracle Java 8 Container - Full + ... 27 [OK]
nimmis/java-centos This is docker images of CentOS 7... 13 [OK]

参数说明:

NAME: 镜像仓库源的名称

DESCRIPTION: 镜像的描述

OFFICIAL: 是否 docker 官方发布

stars: 类似 Github 里面的 star,表示点赞、喜欢的意思。

AUTOMATED: 自动构建。

本地镜像管理

images

docker images: 列出本地镜像。

语法

1
docker images [OPTIONS] [REPOSITORY[:TAG]]

OPTIONS说明:

  • -a: 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);

  • –digests: 显示镜像的摘要信息;

  • -f: 显示满足条件的镜像;

  • –format: 指定返回值的模板文件;

  • –no-trunc: 显示完整的镜像信息;

  • -q: 只显示镜像ID。

实例

查看本地镜像列表。

1
2
3
4
5
6
7
8
9
10
11
12
runoob@runoob:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mymysql v1 37af1236adef 5 minutes ago 329 MB
runoob/ubuntu v4 1c06aa18edee 2 days ago 142.1 MB
<none> <none> 5c6e1090e771 2 days ago 165.9 MB
httpd latest ed38aaffef30 11 days ago 195.1 MB
alpine latest 4e38e38c8ce0 2 weeks ago 4.799 MB
mongo 3.2 282fd552add6 3 weeks ago 336.1 MB
redis latest 4465e4bcad80 3 weeks ago 185.7 MB
php 5.6-fpm 025041cd3aa5 3 weeks ago 456.3 MB
python 3.5 045767ddf24a 3 weeks ago 684.1 MB
...

列出本地镜像中REPOSITORY为ubuntu的镜像列表。

1
2
3
4
root@runoob:~# docker images  ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 90d5884b1ee0 9 weeks ago 188 MB
ubuntu 15.10 4e3b13c8a266 3 months ago 136.3 MB

rmi

docker rmi: 删除本地一个或多个镜像。

语法

1
docker rmi [OPTIONS] IMAGE [IMAGE...]

OPTIONS说明:

  • -f: 强制删除;

  • –no-prune: 不移除该镜像的过程镜像,默认移除;

实例

强制删除本地镜像 runoob/ubuntu:v4。

1
2
3
4
root@runoob:~# docker rmi -f runoob/ubuntu:v4
Untagged: runoob/ubuntu:v4
Deleted: sha2561c06aa18edee44230f93a90a7d88139235de12cd4c089d41eed8419b503072be
Deleted: sha25685feb446e89a28d58ee7d80ea5ce367eebb7cec70f0ec18aa4faa874cbd97c73

tag

docker tag: 标记本地镜像,将其归入某一仓库。

语法

1
docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]

实例

将镜像ubuntu:15.10标记为 runoob/ubuntu:v3 镜像。

1
2
3
4
root@runoob:~# docker tag ubuntu:15.10 runoob/ubuntu:v3
root@runoob:~# docker images runoob/ubuntu:v3
REPOSITORY TAG IMAGE ID CREATED SIZE
runoob/ubuntu v3 4e3b13c8a266 3 months ago 136.3 MB

将使用commit命令创建的镜像,更改保存的仓库和版本号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@OtherServer _data]# docker commit wonderful_austin 
# 基于运行中的容器创建镜像
sha256:10c709b93e37b92108d126c163bc2e5b8172c781e7790e637eef15b20fe4b2f9
[root@OtherServer _data]#
[root@OtherServer _data]# docker images
# 查看镜像信息
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 10c709b93e37 4 hours ago 824MB
nginx latest fa5269854a5e 3 days ago 142MB
docker.elastic.co/kibana/kibana 7.12.0 7a6b1047dd48 13 months ago 1.05GB
docker.elastic.co/elasticsearch/elasticsearch 7.12.0 9337ed510a0c 13 months ago 830MB
docker.elastic.co/logstash/logstash 7.12.0 c283394286f5 13 months ago 971MB
registry.cn-shanghai.aliyuncs.com/yhskc/bwapp latest 0a818cc361a6 19 months ago 552MB
mobz/elasticsearch-head 5 b19a5c98e43b 5 years ago 824MB
[root@OtherServer _data]# docker tag 10c709b93e37 mobz/elasticsearch-head/update:5.1
# 更改镜像所属仓库和版本号
[root@OtherServer _data]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mobz/elasticsearch-head/update 5.1 10c709b93e37 4 hours ago 824MB
nginx latest fa5269854a5e 3 days ago 142MB
docker.elastic.co/kibana/kibana 7.12.0 7a6b1047dd48 13 months ago 1.05GB
docker.elastic.co/elasticsearch/elasticsearch 7.12.0 9337ed510a0c 13 months ago 830MB
docker.elastic.co/logstash/logstash 7.12.0 c283394286f5 13 months ago 971MB
registry.cn-shanghai.aliyuncs.com/yhskc/bwapp latest 0a818cc361a6 19 months ago 552MB
mobz/elasticsearch-head 5 b19a5c98e43b 5 years ago 824MB

build

docker build 命令用于使用 Dockerfile 创建镜像。

语法

1
docker build [OPTIONS] PATH | URL | -

OPTIONS说明:

  • –build-arg=[]: 设置镜像创建时的变量;
  • –cpu-shares: 设置 cpu 使用权重;
  • –cpu-period: 限制 CPU CFS周期;
  • –cpu-quota: 限制 CPU CFS配额;
  • –cpuset-cpus: 指定使用的CPU id;
  • –cpuset-mems: 指定使用的内存 id;
  • –disable-content-trust: 忽略校验,默认开启;
  • -f: 指定要使用的Dockerfile路径;
  • –force-rm: 设置镜像过程中删除中间容器;
  • –isolation: 使用容器隔离技术;
  • –label=[]: 设置镜像使用的元数据;
  • -m: 设置内存最大值;
  • –memory-swap: 设置Swap的最大值为内存+swap,”-1”表示不限swap;
  • –no-cache: 创建镜像的过程不使用缓存;
  • –pull: 尝试去更新镜像的新版本;
  • –quiet, -q: 安静模式,成功后只输出镜像 ID;
  • –rm: 设置镜像成功后删除中间容器;
  • –shm-size: 设置/dev/shm的大小,默认值是64M;
  • –ulimit: Ulimit配置。
  • –squash: 将 Dockerfile 中所有的操作压缩为一层。
  • –tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
  • –network: 默认 default。在构建期间设置RUN指令的网络模式

实例

使用当前目录的 Dockerfile 创建镜像,标签为 runoob/ubuntu:v1。

1
docker build -t runoob/ubuntu:v1 . 

使用URL github.com/creack/docker-firefox 的 Dockerfile 创建镜像。

1
docker build github.com/creack/docker-firefox

也可以通过 -f Dockerfile 文件的位置:

1
$ docker build -f /path/to/a/Dockerfile .

在 Docker 守护进程执行 Dockerfile 中的指令前,首先会对 Dockerfile 进行语法检查,有语法错误时会返回:

1
2
3
$ docker build -t test/myapp .
Sending build context to Docker daemon 2.048 kB
Error response from daemon: Unknown instruction: RUNCMD

history

docker history: 查看指定镜像的创建历史。

语法

1
docker history [OPTIONS] IMAGE

OPTIONS说明:

  • -H: 以可读的格式打印镜像大小和日期,默认为true;

  • –no-trunc: 显示完整的提交记录;

  • -q: 仅列出提交记录ID。

实例

查看本地镜像runoob/ubuntu:v3的创建历史。

1
2
3
4
5
6
root@runoob:~# docker history runoob/ubuntu:v3
IMAGE CREATED CREATED BY SIZE COMMENT
4e3b13c8a266 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 3 months ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.863 kB
<missing> 3 months ago /bin/sh -c set -xe && echo '#!/bin/sh' > /u 701 B
<missing> 3 months ago /bin/sh -c #(nop) ADD file:43cb048516c6b80f22 136.3 MB

save

docker save: 将指定镜像保存成 tar 归档文件。

语法

1
docker save [OPTIONS] IMAGE [IMAGE...]

OPTIONS 说明:

  • -o: 输出到的文件。

实例

将镜像 runoob/ubuntu:v3 生成 my_ubuntu_v3.tar 文档

1
2
3
runoob@runoob:~$ docker save -o my_ubuntu_v3.tar runoob/ubuntu:v3
runoob@runoob:~$ ll my_ubuntu_v3.tar
-rw------- 1 runoob runoob 142102016 Jul 11 01:37 my_ubuntu_v3.ta

load

ocker load: 导入使用 docker save 命令导出的镜像。

语法

1
docker load [OPTIONS]

OPTIONS 说明:

  • –input , -i: 指定导入的文件,代替 STDIN。

  • –quiet , -q: 精简输出信息。

实例

导入镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ docker image ls

REPOSITORY TAG IMAGE ID CREATED SIZE

$ docker load < busybox.tar.gz

Loaded image: busybox:latest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 769b9341d937 7 weeks ago 2.489 MB

$ docker load --input fedora.tar

Loaded image: fedora:rawhide

Loaded image: fedora:20

$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 769b9341d937 7 weeks ago 2.489 MB
fedora rawhide 0d20aec6529d 7 weeks ago 387 MB
fedora 20 58394af37342 7 weeks ago 385.5 MB
fedora heisenbug 58394af37342 7 weeks ago 385.5 MB
fedora latest 58394af37342 7 weeks ago 385.5 MB

import

docker import: 从归档文件中创建镜像。

语法

1
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

OPTIONS说明:

  • -c: 应用docker 指令创建镜像;

  • -m: 提交时的说明文字;

实例

从镜像归档文件my_ubuntu_v3.tar创建镜像,命名为runoob/ubuntu:v4

1
2
3
4
5
runoob@runoob:~$ docker import  my_ubuntu_v3.tar runoob/ubuntu:v4  
sha25663ce4a6d6bc3fabb95dbd6c561404a309b7bdfc4e21c1d59fe9fe4299cbfea39
runoob@runoob:~$ docker images runoob/ubuntu:v4
REPOSITORY TAG IMAGE ID CREATED SIZE
runoob/ubuntu v4 63ce4a6d6bc3 20 seconds ago 142.1 MB

info|version

info

docker info: 显示 Docker 系统信息,包括镜像和容器数。

语法

1
docker info [OPTIONS]

实例

查看docker系统信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker info
Containers: 12
Images: 41
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 66
Dirperm1 Supported: false
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version3.13.0-32-generic
Operating System: Ubuntu 14.04.1 LTS
CPUs: 1
Total Memory: 1.954 GiB
Name: iZ23mtq8bs1Z
ID: M5N4:K6WN:PUNC:73ZN:AONJ:AUHL:KSYH:2JPI:CH3K:O4MK:6OCX:5OYW

version

docker version: 显示 Docker 版本信息。

语法

1
docker version [OPTIONS]

OPTIONS说明:

  • -f:指定返回值的模板文件。

实例

显示 Docker 版本信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker version
Client:
Version1.8.2
API version1.20
Go version: go1.4.2
Git commit0a8c2e3
Built: Thu Sep 10 191900 UTC 2015
OS/Arch: linux/amd64

Server
Version1.8.2
API version1.20
Go version: go1.4.2
Git commit0a8c2e3
Built: Thu Sep 10 191900 UTC 2015
OS/Arch: linux/amd64

Docker Manager

network

Docker network: 管理容器网络

语法

1
docker network COMMAND

COMMAND 说明:

  • connect: 将容器连接到指定的网络
  • create: 创建一个网络
  • disconnect: 断开容器与网络的连接
  • inspect: 显示一个或多个网络的详细信息
  • ls: 显示全部的网络信息
  • prune: 删除所有未使用的网络
  • rm: 删除一个或多个网络

实例

1.ls:查看网络列表

1
docker network ls

2.create:创建一个网络

1
2
docker network create test-create
#不指定网络驱动时默认创建的bridge网络:

创建网络时,使用参数-d指定驱动类型为overlay

1
docker network create -d overlay my-multihost-network

3.rm:删除一个网络.

1
2
docker rm test-create
# ps: 如果网络中有容器连接需要加 -f 参数强制删除,建议不要这样执行,网络中若没有任何容器连接直接执行删除即可

4、inspect: 查看一个网络的详情

1
docker network inspect test-create

5、prune: 删除所有未使用的网络

1
2
docker network prune 
ps: -f 强制删除,不提供任何确认情况下删除

6、connect: 将一个容器加入到一个网络中

1
docker network connect 网络名称 容器ID

7、disconnect: 与 connect 刚好相反, 从网络中断开一个容器的链接

1
2
docker network disconnect 网络名称 容器 ID 
# ps: -f 参数强制删除

8、默认情况下,来自连接到默认网桥网络的容器的流量不会转发到外界。要启用转发,您需要更改两个设置。这些不是Docker命令,它们会影响Docker主机的内核。

配置Linux内核以允许IP转发。

1
2
3
4
5
6
7
8
cat /proc/sys/net/ipv4/ip_forward
#如果下面命令的值为0,说明禁止进行IP转发;如果是1,则说明IP转发功能已经打开。
echo "1" > /proc/sys/net/ipv4/ip_forward
# 临时开启,(写入内存,在内存中开启)
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# 永久开启,(写入内核)
sysctl -p
# 加载,使得配置文件立即生效,等同于sysctl -p /etc/sysctl.conf

将策略的iptables FORWARD策略从更改DROP为 ACCEPT

1
iptables -P FORWARD ACCEPT

volume

Docker volume: 管理容器卷

语法

1
docker volume COMMAND

COMMAND 说明:

  • create: 创建卷
  • inspect: 显示一个或多个卷的详细信息
  • ls: 显示卷
  • prune: 删除所有未使用的卷
  • rm: 删除一个或多个卷

实例

  1. 创建自定义卷

    1
    2
    3
    4
    5
    6
    docker volume create edu-test-vol
    # 创建一个自定义容器卷
    docker volume ls
    # 查看所有容器卷
    docker volume inspect edu-test-vol
    # 查看指定容器卷详情信息

    image-20220424012048998

  2. 创建使用指定卷的容器
    有了自定义容器卷,我们可以创建一个使用这个数据卷的容器,这里我们以nginx为例:

1
docker run -d -it --name=edc-nginx -p 8800:80 -v edu-test-vol:/usr/share/nginx/html nginx

其中,-v代表挂载数据卷,这里使用自定数据卷edc-nginx-vol,并且将数据卷挂载到/usr/share/nginx/html(这个目录是容器中的yum安装nginx的默认网页目录)。如果没有通过-v指定,那么Docker会默认帮我们创建匿名数据卷进行映射和挂载。

image-20220424012436639

创建好容器之后,我们可以进入容器里面看看:

image-20220424012634792

​ 可以看到有两个默认的html文件

查看宿主机目录中是否有文件存在:

1
2
cd /var/lib/docker/volumes/edu-test-vol/_data
ll

​ 可以看到,我们可以访问到容器里面的两个默认页面,由此可知,volume帮我们做的类似于一个软链接的功能。在容器里边的改动,我们可以在宿主机里感知,而在宿主机里面的改动,在容器里边可以感知到。这时,如果我们手动stop并且remove当前nginx容器,我们会发现容器卷里面的文件还在,并没有被删除掉。由此可以验证,在数据卷里边的东西是可以持久化的。如果下次还需要创建一个nginx容器,那么还是复用当前数据卷里面的文件。此外,我们还可以启动多个nginx容器实例,并且共享同一个数据卷,复用性和扩展性较强。

  1. 清理卷
    如果不再使用自定义数据卷了,那么可以手动清理掉:
1
2
3
docker stop edc-nginx // 暂停容器实例
docker rm edc-nginx // 移除容器实例
docker volume rm edc-nginx-vol // 删除自定义数据卷

Docker Network

Docker 网络介绍

在Docker中,默认情况下容器与容器、容器与外部宿主机的网络是隔离开来的。当你安装Docker的时候,docker会创建一个桥接器docker0,通过它才让容器与容器之间、与宿主机之间通信。

1
2
3
4
5
6
7
8
9
10
11
[root@OtherServer ~]# ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:aaff:fe60:d66 prefixlen 64 scopeid 0x20<link>
ether 02:42:aa:60:0d:66 txqueuelen 0 (Ethernet)
RX packets 649 bytes 5424318 (5.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2153 bytes 189201 (184.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

[root@OtherServer ~]#

Docker安装的时候默认会创建三个不同的网络。你可以通过docker network ls命令查看这些网络

1
2
3
4
5
[root@OtherServer ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
c9a6e7cb98fa bridge bridge local
f33fe368e9db host host local
e0a46e9e4327 none null local

Docker 网络模式

按docker官方的说法,docker容器的网络有五种模式:

bridge模式,–net=bridge(默认)
这是dokcer网络的默认设置,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。在docker run启动容器的时候,如果不加–net参数,就默认采用这种网络模式。安装完docker,系统会自动添加一个供docker使用的网桥docker0,我们创建一个新的容器时,容器通过DHCP获取一个与docker0同网段的IP地址,并默认连接到docker0网桥,以此实现容器与宿主机的网络互通。

host模式,–net=host
Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。。

none模式,–net=none
为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。这个模式下,dokcer不为容器进行任何网络配置。需要我们自己为容器添加网卡,配置IP。因此,若想使用pipework配置docker容器的ip地址,必须要在none模式下才可以。

其他容器模式(即container模式,join模式),–net=container:NAME_or_ID
与host模式类似,只是容器将与指定的容器共享网络命名空间。这个模式就是指定一个已有的容器,共享该容器的IP和端口。除了网络方面两个容器共享,其他的如文件系统,进程等还是隔离开的。

用户自定义:
docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。

这些网络模式在相互网络通信方面的对比如下所示:

20200815131735233

南北向通信指容器与宿主机外界的访问机制,东西向流量指同一宿主机上,与其他容器相互访问的机制。

Host模式

由于容器和宿主机共享同一个网络命名空间,换言之,容器的IP地址即为宿主机的IP地址。所以容器可以和宿主机一样,使用宿主机的任意网卡,实现和外界的通信。

其网络模型可以参照下图:

host

采用host模式的容器,可以直接使用宿主机的IP地址与外界进行通信,若宿主机具有公有IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换,而且由于容器通信时,不再需要通过linuxbridge等方式转发或数据包的拆封,性能上有很大优势。当然,这种模式有优势,也就有劣势,主要包括以下几个方面:

  • 最明显的就是容器不再拥有隔离、独立的网络栈。容器会与宿主机竞争网络栈的使用,并且容器的崩溃就可能导致宿主机崩溃,在生产环境中,这种问题可能是不被允许的。

  • 容器内部将不再拥有所有的端口资源,因为一些端口已经被宿主机服务、bridge模式的容器端口绑定等其他服务占用掉了。

Bridge模式

bridge模式是docker默认的。在这种模式下,docker为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,实现容器之间、容器与宿主机之间的网络栈隔离。同时,通过宿主机上的docker0网桥,容器可以与宿主机乃至外界进行网络通信。

其网络模型可以参考下图:

bridge

从上面的网络模型可以看出,容器从原理上是可以与宿主机乃至外界的其他机器通信的。同一宿主机上,容器之间都是连接掉docker0这个网桥上的,它可以作为虚拟交换机使容器可以相互通信。然而,由于宿主机的IP地址与容器veth pair的 IP地址均不在同一个网段,故仅仅依靠veth pair和namespace的技术,还不足以使宿主机以外的网络主动发现容器的存在。为了使外界可以方位容器中的进程,docker采用了端口绑定的方式,也就是通过iptables的NAT,将宿主机上的端口端口流量转发到容器内的端口上。

举一个简单的例子,使用下面的命令创建容器,并将宿主机的3306端口绑定到容器的3306端口:

1
# docker run -tid --name db -p 3306:3306 MySQL

在宿主机上,可以通过iptables -t nat -L -n,查到一条DNAT规则:

1
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.53306

上面的172.17.0.5即为bridge模式下,创建的容器IP。
很明显,bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,对宿主机端口的管理会是一个比较大的问题。同时,由于容器与外界通信是基于三层上iptables NAT,性能和效率上的损耗是可以预见的。

none模式

在这种模式下,容器有独立的网络栈,但不包含任何网络配置,只具有lo这个loopback网卡用于进程通信。也就是说,none模式为容器做了最少的网络设置,但是俗话说得好“少即是多”,在没有网络配置的情况下,通过第三方工具或者手工的方式,开发这任意定制容器的网络,提供了最高的灵活性。

其他容器(container)模式

其他网络模式是docker中一种较为特别的网络的模式。在这个模式下的容器,会使用其他容器的网络命名空间,其网络隔离性会处于bridge桥接模式与host模式之间。当容器共享其他容器的网络命名空间,则在这两个容器之间不存在网络隔离,而她们又与宿主机以及除此之外其他的容器存在网络隔离。

其网络模型可以参考下图:

在这种模式下的容器可以通过localhost来同一网络命名空间下的其他容器,传输效率较高。而且这种模式还节约了一定数量的网络资源,但它并没有改变容器与外界通信的方式。在一些特殊的场景中非常有用,例如,kubernetes的pod,kubernetes为pod创建一个基础设施容器,同一pod下的其他容器都以其他容器模式共享这个基础设施容器的网络命名空间,相互之间以localhost访问,构成一个统一的整体。

用户定义网络模式

在用户定义网络模式下,开发者可以使用任何docker支持的第三方网络driver来定制容器的网络。并且,docker 1.9以上的版本默认自带了bridge和overlay两种类型的自定义网络driver。可以用于集成calico、weave、openvswitch等第三方厂商的网络实现。 除了docker自带的bridge driver,其他的几种driver都可以实现容器的跨主机通信。而基于bdrige driver的网络,docker会自动为其创建iptables规则,保证与其他网络之间、与docker0之间的网络隔离。 例如,使用下面的命令创建一个基于bridge driver的自定义网络:

1
docker network create bri1

则docker会自动生成如下的iptables规则,保证不同网络上的容器无法互相通信。

1
2
# -A DOCKER-ISOLATION -i br-8dba6df70456 -o docker0 -j DROP
# -A DOCKER-ISOLATION -i docker0 -o br-8dba6df70456 -j DROP

除此之外,bridge driver的所有行为都和默认的bridge模式完全一致。而overlay及其他driver,则可以实现容器的跨主机通信。

Docker 容器端口映射

创建了一个 python 应用的容器。

1
2
runoob@runoob:~$ docker run -d -P training/webapp python app.py
fce072cc88cee71b1cdceb57c2821d054a4a59f67da6b416fceb5593f059fc6d

另外,我们可以指定容器绑定的网络地址,比如绑定 127.0.0.1。

我们使用 -P 绑定端口号,使用 docker ps 可以看到容器端口 5000 绑定主机端口 32768。

1
2
3
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
fce072cc88ce training/webapp "python app.py" ... 0.0.0.032768->5000/tcp grave_hopper

我们也可以使用 -p 标识来指定容器端口绑定到主机端口。

两种方式的区别是:

  • -P:是容器内部端口随机映射到主机的端口。
  • -p: 是容器内部端口绑定到指定的主机端口。
1
2
3
4
5
6
runoob@runoob:~$ docker run -d -p 50005000 training/webapp python app.py
33e4523d30aaf0258915c368e66e03b49535de0ef20317d3f639d40222ba6bc0
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
33e4523d30aa training/webapp "python app.py" ... 0.0.0.05000->5000/tcp berserk_bartik
fce072cc88ce training/webapp "python app.py" ... 0.0.0.032768->5000/tcp grave_hopper

另外,我们可以指定容器绑定的网络地址,比如绑定 127.0.0.1。

1
2
3
4
5
6
7
runoob@runoob:~$ docker run -d -p 127.0.0.150015000 training/webapp python app.py
95c6ceef88ca3e71eaf303c2833fd6701d8d1b2572b5613b5a932dfdfe8a857c
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
95c6ceef88ca training/webapp "python app.py" ... 5000/tcp, 127.0.0.15001->5000/tcp adoring_stonebraker
33e4523d30aa training/webapp "python app.py" ... 0.0.0.05000->5000/tcp berserk_bartik
fce072cc88ce training/webapp "python app.py" ... 0.0.0.032768->5000/tcp grave_hopper

这样我们就可以通过访问 127.0.0.1:5001 来访问容器的 5000 端口。

上面的例子中,默认都是绑定 tcp 端口,如果要绑定 UDP 端口,可以在端口后面加上 /udp

1
2
3
4
5
6
7
8
runoob@runoob:~$ docker run -d -p 127.0.0.150005000/udp training/webapp python app.py
6779686f06f6204579c1d655dd8b2b31e8e809b245a97b2d3a8e35abe9dcd22a
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
6779686f06f6 training/webapp "python app.py" ... 5000/tcp, 127.0.0.15000->5000/udp drunk_visvesvaraya
95c6ceef88ca training/webapp "python app.py" ... 5000/tcp, 127.0.0.15001->5000/tcp adoring_stonebraker
33e4523d30aa training/webapp "python app.py" ... 0.0.0.05000->5000/tcp berserk_bartik
fce072cc88ce training/webapp "python app.py" ... 0.0.0.032768->5000/tcp grave_hopper

docker port 命令可以让我们快捷地查看端口的绑定情况。

1
2
runoob@runoob:~$ docker port adoring_stonebraker 5000
127.0.0.15001

Docker 容器互联

端口映射并不是唯一把 docker 连接到另一个容器的方法。

docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。

docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。

新建网络

下面先创建一个新的 Docker 网络。

1
$ docker network create -d bridge test-net

img

参数说明:

-d:参数指定 Docker网络类型,有bridge、overlay。

其中 overlay 网络类型用于Swarm mode,在本小节中你可以忽略它。

创建容器并指定网络

运行一个容器并连接到新建的 test-net 网络:

1
$ docker run -itd --name test1 --network test-net ubuntu /bin/bash

打开新的终端,再运行一个容器并加入到 test-net 网络:

1
$ docker run -itd --name test2 --network test-net ubuntu /bin/bash

img

下面通过 ping 来证明 test1 容器和 test2 容器建立了互联关系。

如果 test1、test2 容器内中无 ping 命令,则在容器内执行以下命令安装 ping(即学即用:可以在一个容器里安装好,提交容器到镜像,在以新的镜像重新运行以上俩个容器)。

1
2
$ apt-get update
$ apt install iputils-ping

在 test1 容器输入以下命令

img

同理在 test2 容器也会成功连接到:

img

这样,test1 容器和 test2 容器建立了互联关系。

如果你有多个容器之间需要互相连接,推荐使用 Docker Compose,后面会介绍。

配置DNS

我们可以在宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS:

1
2
3
4
5
6
{
"dns"[
"114.114.114.114",
"8.8.8.8"
]
}

设置后,启动容器的 DNS 会自动配置为 114.114.114.114 和 8.8.8.8。

配置完,需要重启 docker 才能生效。

查看容器的 DNS 是否生效可以使用以下命令,它会输出容器的 DNS 信息:

1
$ docker run -it --rm  ubuntu  cat etc/resolv.conf

img

手动指定容器的配置

如果只想在指定的容器设置 DNS,则可以使用以下命令:

1
$ docker run -it --rm -h host_ubuntu  --dns=114.114.114.114 --dns-search=test.com ubuntu

参数说明:

–rm:容器退出时自动清理容器内部的文件系统。

-h HOSTNAME 或者 –hostname=HOSTNAME: 设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts。

–dns=IP_ADDRESS: 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。

–dns-search=DOMAIN: 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com。

img

如果在容器启动时没有指定 –dns–dns-search,Docker 会默认用宿主主机上的 /etc/resolv.conf 来配置容器的 DNS。

Docker Volume

Docker volume 介绍

在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:

volumes

Docker管理宿主机文件系统的一部分,默认位于/var/lib/docker/volumes目录中;

image-20220424010536577

由上图可以知道,目前所有Container的数据都保存在了这个目录下边,由于没有在创建时指定卷,所以Docker帮我们默认创建许多匿名(就上面这一堆很长ID的名字)卷。

注意:如果volume是空的而container中的目录有内容,那么docker会将container目录中的内容拷贝到volume中,但是如果volume中已经有内容,则会将container中的目录覆盖。

bind

bind mounts:意为着可以存储在宿主机系统的任意位置;(比较常用的方式)
bind mount:在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。
有几点需要注意:

  1. host机器的目录路径必须为全路径(准确的说需要以/或~/开始的路径),不然docker会将其当做volume而不是路径来处理
  2. 如果host机器上的目录不存在,docker会自动创建该目录
  3. 如果container中的目录不存在,docker会自动创建该目录
  4. 如果container中的目录已经有内容,那么docker会使用host上的目录将其覆盖掉

tmpfs

挂载存储在宿主机系统的内存中,不会将数据写入宿主机的文件系统。(一般都不会用的方式)

Docker volume Bind Mounts的基本使用

  1. 使用卷创建一个容器

    1
    2
    docker run -d -it --name=edu-nginx -v /app/wwwroot:/usr/share/nginx/html nginx
    10b32e875c821e03f52623ea7aa194b113adc2e62a96902911a891a58822f53d

    这里指定了将宿主机上的 /app/wwwroot 目录(如果没有会自动创建)挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)。

    这时我们再次进入容器内部看看:

    1
    2
    3
    4
    5
    6
    [root@OtherServer _data]# docker exec -it edu-nginx bash
    root@10b32e875c82:/# cd /usr/share/nginx/html/
    root@10b32e875c82:/usr/share/nginx/html# ll
    bash: ll: command not found
    root@10b32e875c82:/usr/share/nginx/html# ls
    root@10b32e875c82:/usr/share/nginx/html#

image-20220424013952280

可以看到,与volumes不同,bind mounts的方式会隐藏掉被挂载目录里面的内容(如果非空的话),这里是/usr/share/nginx/html 目录下的内容被隐藏掉了,因此我们看不到。

但是,我们可以将宿主机上的文件随时挂载到容器中:

  • 在宿主机/app/wwwroot目录下新建一个index.html

    image-20220424014355718

  • 在容器中查看

    image-20220424014435705

  1. 验证绑定

    1
    docker inspect edc-nginx

    通过上述命令可以看到一大波配置,我们要关注的是:

    image-20220424014719863

  2. 清理

    1
    2
    docker stop edc-nginx
    docker rm edc-nginx

    同volumes一样,当我们清理掉容器之后,挂载目录里面的文件仍然还在,不会随着容器的结束而消失,从而实现数据持久化。

  3. 应用案例
    在服务治理组件中,服务发现组件是一个最常用的组件之一,Consul是一个流行的服务发现开源项目,Consul推荐我们使用配置文件的方式注册服务信息。因此,我们常常会将填写好服务注册配置文件放在宿主机的一个文件目录下将其挂载到Consul的容器指定目录下,如下所示:

    1
    2
    3
    4
    5
    docker run -d -p 8500:8500 --restart=always \
    -v /XiLife/consul/data/server1:/consul/data -v /XiLife/consul/conf/server1:/consul/config \
    -e CONSUL_BIND_INTERFACE='eth0' --privileged=true \
    --name=consul_server_1 consul:1.4.4 agent -server -bootstrap-expect=3 -ui -node=consul_server_1 -client='0.0.0.0' \
    -data-dir /consul/data -config-dir /consul/config -datacenter=xdp_dc;

    可以看到,我们通过Bind Mounts的方式将宿主机上的/XiLife/consul/data/server1目录挂载到了容器的/consul/data目录下,还将/XiLife/consul/conf/server1目录挂载到了容器的/consul/config目录下,而容器下的两个目录/consul/data和/consul/config则是我们指定的存放agent数据和配置文件的地方。因此,宿主机上的配置文件的变化会及时反映到容器中,比如我们在宿主机上的目录下更新了配置文件,那么只需要reload一下Consul的容器实例即可:

    1
    docker exec consul-server consul reload

    这里的consul-server是容器的名字,consul reload是重新加载的命令(非restart)。

    1
    docker volume prune
  4. 移除未使用的数据卷

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    [root@OtherServer wwwroot]# docker volume ls
    DRIVER VOLUME NAME
    local 6ff5a15228e8f62b25ecba5d5ea84ce4ed79236497fc76358d2edf7d94ef0b81
    local 558c8223ecea79deb79611538cfc998dab102f2cb49662e72d31c8ec6d20f922
    local a9448253964b939dd87975e6c8248c2610bf15aae30805b1757eb6c09931a677
    local bef0b8445225cc286ea0c4e5972b29bc1231d9658d96c4642935f9aa70c1f7b7
    local caafaab64d2d03007ccbb763e123cd343b4c7c70c4a94aeabff0bd069a33e20f
    local containerd_data01
    local containerd_data02
    local containerd_data03
    local data01
    local data02
    local data03
    local e42d514084e68774ce7186b851b7e58f220da20c22f8e74c6cdede32f1d06913
    local edu-test-vol

    [root@OtherServer wwwroot]# docker volume prune
    WARNING! This will remove all local volumes not used by at least one container.
    Are you sure you want to continue? [y/N] y
    Deleted Volumes:
    a9448253964b939dd87975e6c8248c2610bf15aae30805b1757eb6c09931a677
    data01
    data03
    e42d514084e68774ce7186b851b7e58f220da20c22f8e74c6cdede32f1d06913
    558c8223ecea79deb79611538cfc998dab102f2cb49662e72d31c8ec6d20f922
    bef0b8445225cc286ea0c4e5972b29bc1231d9658d96c4642935f9aa70c1f7b7
    data02
    Total reclaimed space: 30.44MB

    [root@OtherServer wwwroot]# docker volume ls
    DRIVER VOLUME NAME
    local 6ff5a15228e8f62b25ecba5d5ea84ce4ed79236497fc76358d2edf7d94ef0b81
    local caafaab64d2d03007ccbb763e123cd343b4c7c70c4a94aeabff0bd069a33e20f
    local containerd_data01
    local containerd_data02
    local containerd_data03
    local edu-test-vol

Docker Dockerfile

什么是Dockerfile?

​ Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

使用Dockerfile定制镜像

​ 这里仅讲解如何运行 Dockerfile 文件来定制一个镜像,具体 Dockerfile 文件内指令详解,将在下一节中介绍,这里你只要知道构建的流程即可。

1、下面以定制一个 nginx 镜像(构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件)

​ 在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:

1
2
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

img

2、FROM 和 RUN 指令的作用

FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

RUN:用于执行后面跟着的命令行命令。有以下俩种格式:

  • shell 格式:
1
2
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
  • exec 格式:
1
2
3
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

1
2
3
4
FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。可简化为以下格式:

1
2
3
4
FROM centos
RUN yum -y install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

开始构建镜像

在 Dockerfile 文件的存放目录下,执行构建动作。

以下示例,通过目录下的 Dockerfile 构建一个 nginx:v3(镜像名称:镜像标签)。

:最后的 . 代表本次执行的上下文路径,下一节会介绍。

1
$ docker build -t nginx:v3 .

docker-dockerfile2

以上显示,说明已经构建成功。

上下文路径

上一节中,有提到指令最后一个 . 是上下文路径,那么什么是上下文路径呢?

1
$ docker build -t nginx:v3 .

上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

指令详解

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:

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

**[–chown=]**:可选参数,用户改变复制到容器内文件的拥有者和属组。

**<源路径>**:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

1
2
COPY hom* /mydir/
COPY hom?.txt /mydir/

**<目标路径>**:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

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

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

格式:

1
2
3
CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 –entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

格式:

1
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

1
2
3
4
FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参

1、不传参运行

1
$ docker run  nginx:test

容器内会默认运行以下命令,启动主进程。

1
nginx -c /etc/nginx/nginx.conf

2、传参运行

1
$ docker run  nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

1
nginx -c /etc/nginx/new.conf

ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

格式:

1
2
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

1
2
3
4
ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

ARG

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 –build-arg <参数名>=<值> 来覆盖。

格式:

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

VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。

格式:

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

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

EXPOSE

仅仅只是声明端口。

作用:

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

格式:

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

WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

格式:

1
WORKDIR <工作目录路径>

USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

格式:

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

HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

格式:

1
2
3
4
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令>: 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

格式:

1
ONBUILD <其它指令>

LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

1
LABEL <key>=<value> <key>=<value> <key>=<value> ...

比如我们可以添加镜像的作者:

1
LABEL org.opencontainers.image.authors="runoob"

参考链接:

https://www.runoob.com/docker/docker-tutorial.html

https://blog.csdn.net/lihongbao80/article/details/108019773

https://blog.csdn.net/lihongbao80/article/details/122812274


Docker学习笔记
https://hesc.info/c69f4340f6e7/
作者
需要哈气的纸飞机
发布于
2022年4月24日
许可协议