docker 手册
docker
学习大纲
2022//8/26
- Docker 概述
- Docker 安装
- Docker 命令
- 镜像命令
- 容器命令
- 操作命令
- ... ...
- Docker 镜像
- DockerFile
- Docker网络原理
- IDEA整合Docker
- Docker Compose
- Docker Swarm (简化版 k8s)
- CI \ CD Jenkins
1. Docker概述
1.1 出现的场景
一套产品:开发 ——> 上线, 两套环境(开发环境, 生产环境) --> 应用环境, 应用配置
开发->运维
问题: 在开发环境可以正常运行, 但是在其他环境下有可能出现问题, 导致服务不可用
环境配置比较费时费力, 可以通过Docker进行环境配置
发布一个项目: (jar/war + (各种环境配置)) ,项目上线时携带环境配置
传统: 开发jar, 运维上线
现在: 开发打包部署上线, 一套流程做完
类比:
开发起点 | 打包 | 发布 | 使用 |
---|---|---|---|
java | apk | 应用商店 | 安装即可用 |
java | jar(带上环境) | Docker仓库 | 下载镜像运行即可用 |

Docker的思想就来自于集装箱!
Jre --> 多个应用(端口冲突) --> 原来都是交叉的
Docker --> 隔离! --> 打包装箱, 每个箱子都是相互隔离的
1.2 Docker历史
- 2010年, 几个搞IT的年轻人, 在美国成立了一家公司 -- dotCloud 做一些
pass
的云计算服务(Linux 虚拟机有关的容器技术 --- LXC)
参考:云计算
他们将自己的技术(容器化技术)命名就是Docker,这时他们想到了开源,越来越多的人发现了Docker的优点,火了!
- 2014年4月9日,Docker1.0 发布
在容器化技术出来之前,我们都是使用虚拟机技术,二者比较:
虚拟机 | 容器技术 | |
---|---|---|
定义 | 虚拟机是基于硬件的多个客户操作系统,由虚拟机监视器实现 | 容器是应用程序级构造,并模拟共享单个内核的多个虚拟环境 |
性能 | 分钟 对于使用虚拟机的传统虚拟化,每个虚拟机都有自己的完整操作系统,因此在运行内置于虚拟机的应用程序时,内存使用量可能会高于必要值,虚拟机可能会开始耗尽主机所需的资源 | 秒 与传统的容器化应用程序不同,共享操作系统环境(内核),因此它们比完整虚拟机使用更少的资源,并减轻主机内存的压力 |
重量 | GB:传统虚拟机可占用大量磁盘空间:除了虚拟机托管的任何应用程序外,它们还包含完整的操作系统和相关工具。 | MB容器相对较轻:它们仅包含使容器化应用程序运行所需的库和工具,因此它们比虚拟机更紧凑,并且启动速度更快。 |
维护与更新 | 在更新或修补操作系统时,必须逐个更新传统计算机:必须单独修补每个客户操作系统。 | 对于容器,只需更新容器主机(托管容器的机器)的操作系统。这显著简化了维护。 |
- 重量

- 维护和更新

小结:
虚拟机技术缺点:
- 资源占用十分多
- 冗余步骤多
- 启动很慢
1.3 Docker闲谈
Docker 是基于GO语言
开发的,开源项目!
1.4 Docker用处
容器化技术:不是模拟一个完整的操作系统
Docker与虚拟机技术的不同:
- 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在宿主机的内核上,容器是没有自己的内核的,也没有虚拟计算机硬件,因此跟家轻便
- 每个容器之间互相隔离,每个容器内都有一个属于自己的文件系统,互不影响
DevOps(开发、运维)
应用更快速的交付和部署
传统:一堆帮助文档,按住程序
Docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
使用了Docker后,我们部署应用就和搭积木一样
项目打包为一个镜像,可以方便地拓展服务器
更简单的系统运维
开发和测试环境是高度一致的
更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例
1.5 Docker术语
-
镜像(Image)
docker镜像类似于一个模板,可以通过这个模板来创建多个容器服务(最终服务运行或者项目运行就是在容器里的)
-
容器(container)
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的
- 启动、停止、删除等基本命令
- 理解为:简易的Linux系统
-
仓库(repository)
仓库就是存放镜像的地方
仓库分为公有仓库(Docker Hub、Aliyun、TencentCloud)和私有仓库:
2. Docker安装
环境准备
Linux 服务器
-
环境查看
-
系统内核版本:
uname -r
-
系统环境:
cat /etc/os-releasc
NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"
-
2.1 Docker Engine(官网手册)
https://docs.docker.com/engine/install/centos/#prerequisites
2.1.1 卸载旧版本
旧版本的Docker可以被称为docker
或者docker-engine
, 使用下面的命令进行卸载
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
如果成功, yum会返回这些没有安装.

2.1.2 安装方法
你可以根据你的需要,以不同的方式安装Docker Engine:
-
大多数用户设置Docker的存储库并从其中进行安装,以简化安装和升级任务。这是推荐的方法。
-
部分用户下载并手动安装RPM包,完全通过手动方式进行升级管理。这在一些情况下很有用,比如在没有互联网接入的系统上安装Docker。
-
在测试和开发环境中,一些用户选择使用自动化脚本来安装Docker。
方法 | 适合场景 | 适合人群 |
---|---|---|
设置Docker的存储库 | ||
下载并手动安装RPM包 | ||
自动化脚本 |
2.1.3 安装 (推荐方法)
在新机器上首次安装Docker Engine之前, 首先需要设置Docker 仓库, 之后就可以在存储库中进行Docker的安装以及更新了!
-
设置存储资源库
安装
yum-utils
包, 它提供了yum-config
sudo yum install -y yum-utils
-
设置存储库镜像
# 默认为国外服务器 sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # aliyun sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
-
安装Docker Engine
-
安装最新版本
sudo yum install docker-ce docker-ce-cli \ containerd.io docker-compose-plugin
这个命令会安装Docker,但不会启动Docker。它还创建了一个docker组,但是默认情况下它不会向该组添加任何用户
如果提示接受GPG key[如下图], 检查fingerprint是否与
060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35
相同, 如果相同就接受它 -
安装指定版本
首先可以将存储库中可安装的版本列出来,之后选择其中一个并安装:
列出并排序在存储库中的版本。版本号对结果进行排序,从最高到最低:
yum list docker-ce --showduplicates | sort -r
通过它的完全限定包名安装一个特定的版本,这是包名(docker-ce)加上版本字符串(第二列),从第一个冒号(:)开始,直到第一个连字符,由连字符(-)分隔。例如,docker-ce-18.09.1。
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io docker-compose-plugin
-
启动Docker
sudo systemctl start docker
-
查看Docker版本
-
通过运行
hello-world
检查是否正确安装sudo docker run hello-world
这个命令下载一个测试映像,并在容器中运行它。当容器运行时,它打印一条消息并退出。
-
通过命令查看镜像
可以看到刚才测试拉取的远程镜像
hello-world
-
2.1.4 更新方法
先卸载再安装
2.1.5 卸载方法
-
卸载Docker Engine, CLI, Containerd 和Docker Compose 包:
sudo yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
-
删除所有的映像、容器、卷或自定义配置文件
sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd
docker的默认工作路径
/var/lib/docker
2.2 aliyun镜像加速
- 开启镜像加速器
免费使用!不要看错了
- 配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://pg7rwnnq.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
3. Docker基本原理(实践前后学习)
3.1 前置
Docker是如何工作的?
Docker 为什么比VM快 ?
- Docker有更少的抽象层
- 利用了宿主机的内核, VM需要Guest OS


3.2 Docker镜像原理
镜像是什么?
镜像是一种轻量级的、可执行的独立软件包, 用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件
所有的应用,直接打包docker镜像,就可以直接跑起来
镜像的获得方式
- 远程
- 复制
- 自己制作一个镜像
DockerFile
3.2.1 Docker镜像加载
UnionFS(联合文件系统)
UnionFS是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)
UnionFS是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性: 一次加载多个文件系统,但从外面看,只能看到一个文件系统,联合加载会把各层文件叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载
Docker的镜像实际上是由一层一层的文件系统(UnionFS)组成的。
bootfs(boot file system)主要包括bootloader
和kernel
, 主要是引导加载Kernel
, Linux刚启动会加载Bootfs文件系统, 在Docker镜像的最底层是bootfs.这一层与我们典型的Linux/Unix系统是一样的, 包含Boot加载器和内核。当boot加载完成后整个内核就在内存中了,此时内存的使用权已有bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system)在bootsf之上,包含的就是典型Linux系统中的/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu、CentOS等等
对于一个精简的OS,rootfs
可以很小,只需要包含最基本的命令, 工具和程序库就可以了. 因为底层直接用host的Kernal, 自己只需要提供rootfs就可以了.由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs.
Docker分层举例
可以看到有些层是已经存在了的~
理解:
所有的Docker镜像都开始于一个基础镜像层,当金星修改或增加新的内容是,就会在当前镜像层之上,创建新的镜像层。
eg. 基于Ubuntu 16.04创建一个新的镜像,这就是新镜像的第一层; 如果在该镜像中添加python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁就会创建第三个镜像层.
如下图,该镜像就包含三个镜像层,

在添加额外的镜像层的同时,镜像事中保持当前所有镜像的组合, 如下图,每个镜像层包含3个文件, 而镜像包含了来自两个镜像层的6个文件.

上图中的镜像层跟之前图中的略有区别, 主要目的是便于展示文件.
下图中展示了一个稍微复杂的三层镜像, 在外部看来整个镜像只有6个文件, 这是因为最上层中的文件7是文件5的更新版本.

这种情况下, 上层镜像层中的文件覆盖了底层镜像层中的文件, 这样就使得文件的更新版本作为一个新镜像层添加到镜像当中.
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈, 并保证多镜像曾对外展示为统一的文件系统
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应
文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持WindowsFilter一种存储引擎,该引擎基于NTFS文件系统上实现了分层和Cow。
下图展示了与系统西安市相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

Docker 镜像特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器之下的都叫镜像层。
3.2.2 Commit镜像
docker commit 容器id 目标镜像名[:TAG] # 提交容器成为一个新的副本
-m="xxx" # 提交的描述信息
-a="aaa" # 容器的作者
-
启动最新默认tomcat
root@su-codeink: ~ # docker run -d --name tomcatTest -p 7001:8080 tomcat Unable to find image 'tomcat:latest' locally latest: Pulling from library/tomcat 0e29546d541c: Already exists 9b829c73b52b: Already exists cb5b7ae36172: Already exists 6494e4811622: Already exists 668f6fcc5fa5: Already exists dc120c3e0290: Already exists 8f7c0eebb7b1: Already exists 77b694f83996: Already exists 0f611256ec3a: Pull complete 4f25def12f23: Pull complete Digest: sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324 Status: Downloaded newer image for tomcat:latest 456270e5ef5f6afc06f128fc3fa71df9ccac0b322bb4d2e33940bafcb8540f13 root@su-codeink: ~ # docker ps CONTAINER ID IMAGE CREATED STATUS PORTS NAMES 456270e5ef5f tomcat 21 seconds ago Up 20 seconds 0.0.0.0:7001->8080/tcp, :::7001->8080/tcp tomcatTest
-
进入tomcat做一些修改后, 可用
commit
命令来提交, 获得一个镜像root@su-codeink: ~ # docker commit -a="codeink" -m="copy webapps.dict/* to webapps" 456270e5ef5f tomcat-codeink:1.0.0.SNAP sha256:57b50f32fde37a5407101559a1f04f51913c7f467d6c706c3b5a51d3f065bf85
4. Docker使用
4.1 Docker常用命令
4.1.1 帮助命令
docker version # 显示Docker的版本信息
docker info # 显示Docker的系统信息
docker --help # 查看使用说明
4.1.2 镜像命令
运行docker需要root权限
-
docker images
Repository --> 镜像的仓库
tag --> 镜像的标签
image id --> 镜像的id
created --> 镜像的创建时间
size --> 镜像的大小
-
docker search xxx
--> 搜索镜像docker search xxx [--fiter=STARS=3000] # 对搜索结果进行过滤
-
docker pull
--> 下载镜像# docker pull xxx[:tag]
-
docker rmi
--> 删除镜像docker rmi -f 镜像id docker rmi -f 镜像id 镜像id 镜像id # 根据镜像id 删除多个镜像 docker rmi -f $(docker images -aq) # 删除全部镜像
4.1.3 容器命令
有镜像才能创建容器
docker pull ubuntu
-
新建并启动容器
docker run [参数] xxx
-name="" 容器名字 tomcat-1 tomcat-2, 用以区分容器 -d: 后台方式运行 -it: 使用交互方式运行, 进入容器查看内容 -p: 指定容器的端口 # 使用方式 # -p ip:主机端口:容器端口 # -p 主机端口:容器端口(常用) # -p 端口 -P: 随机指定端口
启动并进入容器
-it
后台启动容器
-d
发现容器停止了!
原因: 必须要有一个前台进程, 如果没有前台进程就会自动停止
-
启动容器
start
docker start 容器id docker restart 容器id
-
停止容器
docker stop 容器id # 停止容器 docker stop 容器名 docker kill 容器id # 强制停止容器
-
查看正在运行的容器
docker ps # 列出全部运行中的容器 -a # 列出全部容器(包括已经结束了的) -n=? # 列出最近创建n的容器(排序输出+limit)
技巧:(格式化输出)
.ID - Container ID .Image - Image ID .Command - Quoted command .CreatedAt - Time when the container was created. .RunningFor - Elapsed time since the container was started. .Ports - Exposed ports. .Status - Container status. .Size - Container disk size. .Names - Container names. .Labels - All labels assigned to the container. .Label - Value of a specific label for this container. For example {{.Label "com.docker.swarm.cpu"}} .Mounts - Names of the volumes mounted in this container. docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}"
-
退出容器
exit # 退出容器并结束容器运行 Ctrl+P+Q# 仅退出容器
-
删除容器
运行中的容器无法直接删除, 但可以强制删除
docker rm 容器id docker rm $(docker ps -aq) docker rm -f $(docker ps -aq) # 强制删除所有容器 docker ps -a -q | xargs docker rm # 强制删除所有容器(管道方式)
4.1.4 其他命令
1) 日志命令
-
日志的帮助命令
docker logs --help 输出: Usage: docker logs [OPTIONS] CONTAINER Fetch the logs of a container Options: --details Show extra details provided to logs -f, --follow Follow log output --since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) -n, --tail string Number of lines to show from the end of the logs (default "all") -t, --timestamps Show timestamps --until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-
查看日志
docker logs -tf 容器id # 根据提示信息可知 -t: # 显示时间戳 -f: # 流式输出, 一直输出 -tail n # 选择开始时输出的日志条数

-tf 条件输出

-f 条件输出
2) 查看容器进程
root@su-codeink: ~ # docker top 5f694cc63f51
UID PID PPID C STIME TIME CMD
root 2320 2301 0 19:19 00x3 /bin/sh -c while true;do echo 111;sleep 1;done
root 4267 2320 0 19:28 00x3 sleep 1
3) 查看容器的元数据
root@su-codeink: ~ # docker inspect --help
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
--type string Return JSON for specified type
root@su-codeink: ~ # docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
5f694cc63f51 ubuntu "/bin/sh -c 'wh…" 16 minutes ago Up 16 minutes kind_euclid
- 查看指定容器的元数据
root@su-codeink: ~ # docker inspect 5f694cc63f51
[
{
"Id": "5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5",
"Created": "2022-08-30T11:19:23.191647333Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo 111;sleep 1;done "
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 2320,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-08-30T11:19:23.540286636Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1",
"ResolvConfPath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/hostname",
"HostsPath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/hosts",
"LogPath": "/var/lib/docker/containers/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5/5f694cc63f51526219864f72f15b03a67baa65236c1ad979bb7f44b70216e3e5-json.log",
"Name": "/kind_euclid",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68-init/diff:/var/lib/docker/overlay2/fbda1c5d5272b0dbfda0973b21d0a8586e519542fe50c0b485068992a8857673/diff",
"MergedDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68/merged",
"UpperDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68/diff",
"WorkDir": "/var/lib/docker/overlay2/f8f3805a835bd4e3cd3e558d34eb72871db03525c7324120e5c3c0608b9c6b68/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "5f694cc63f51",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"while true;do echo 111;sleep 1;done "
],
"Image": "ubuntu",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "1b2e76d053114e1777c37b9cdbfa37891adc81c8eaadab59f6d881affb1835ae",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/1b2e76d05311",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "c2530f6d8f6da5e8c0fc7d0cc4edf323401a272da146f18484208d0bc2bb14c4",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "8f746dac50cd1aed398b87909d5b9ba7a943e1e0ec72a5f98f96485a7bc580c8",
"EndpointID": "c2530f6d8f6da5e8c0fc7d0cc4edf323401a272da146f18484208d0bc2bb14c4",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
4) 进入正在运行的容器
-
docker exec
进入容器后,开启一个新的终端, 可以在新的终端里进行一些常用操作
root@su-codeink: ~ # docker exec -it 5f694cc63f51 /bin/bash root@5f694cc63f51:/# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 11:19 ? 00:00:00 /bin/sh -c while true;do echo 111;sleep 1;done root 1335 0 0 11:41 pts/0 00:00:00 /bin/bash root 1354 1 0 11:41 ? 00:00:00 sleep 1 root 1355 1335 0 11:41 pts/0 00:00:00 ps -ef root@5f694cc63f51:/# ls bin boot dev etc home lib lib32 lib64 libx32 ...
-
docker attach
进入容器正在执行的终端, 不会启动新的进程
5) 从容器内拷贝文件到主机上
docker cp
# 进入容器环境
root@su-codeink: ~ # docker attach b416aebb6a3c
root@b416aebb6a3c:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
root@b416aebb6a3c:/# cd home
root@b416aebb6a3c:/home# ls
# 在容器内新建一个文件
root@b416aebb6a3c:/home# touch 111.txt
# 向该文件输入111
root@b416aebb6a3c:/home# echo 111 >111.txt
# 查看写入是否成功
root@b416aebb6a3c:/home# cat 111.txt
111
# 退出容器环境
root@b416aebb6a3c:/home# read escape sequence
root@su-codeink: ~ # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b416aebb6a3c ubuntu "/bin/bash" About a minute ago Up About a minute cool_borg
以上命令在容器内创建了一个文件, 之后需要将该文件复制出来:
root@su-codeink: ~ # docker cp b416aebb6a3c:/home/111.txt /root/test
# 本命令的格式为:
# docker cp 容器id:容器内文件 主机目录
如下图所示, 文件成功拷贝出来了!

可以使用 -v 卷的技术, 实现将容器内目录与主机的目录进行绑定
4.2 安装常用容器
4.2.1 安装Nginx
-
安装稳定版的Nginx
docker pull nginx:stable
root@su-codeink: ~ # docker pull nginx:stable stable: Pulling from library/nginx a2abf6c4d29d: Pull complete da03644a1293: Pull complete dcbfc6badd70: Pull complete 3f7ccff97047: Pull complete 49e31097680b: Pull complete c423e1dacb26: Pull complete Digest: sha256:03f3cb0afb7bd5c76e01bfec0ce08803c495348dccce37bcb82c347b4853c00b Status: Downloaded newer image for nginx:stable docker.io/library/nginx:stable
-
查看镜像
root@su-codeink: ~ # docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx stable 50fe74b50e0d 8 months ago 141MB ubuntu latest ba6acccedd29 10 months ago 72.8MB hello-world latest feb5d9fea6a5 11 months ago 13.3kB
-
启动容器并指定端口
root@su-codeink: ~ # docker run -d --name nginx01 -p 7001:80 nginx:stable efe325c93ba4c90ba3cd5f49b6709626bf24e1dc8f65e26fd88ed67791c5a395
端口暴露: 主机的7001端口关联到容器里的80端口
-
显示!
-
进入容器
root@su-codeink: ~ # docker exec -it nginx01 /bin/bash root@efe325c93ba4:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@efe325c93ba4:/# cd etc/nginx/ root@efe325c93ba4:/etc/nginx# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
-
在外部修改容器配置文件
每次修改容器都要进入容器内部?
- v 数据卷技术: 提供外部映射
4.2.2 安装tomcat
-
使用tomcat
docker run -it --rm -p 7002:8080 tomcat:9.0 # --rm: 用完即删 docker run -it -p 7002:8080 tomcat:9.0
-
查看
-
进入容器
root@su-codeink: ~ # docker exec -it a023804512d5 /bin/bash # -it 以交互方式进入容器 root@a023804512d5:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@a023804512d5:/usr/local/tomcat# ls -al total 172 drwxr-xr-x 1 root root 4096 Dec 22 2021 . drwxr-xr-x 1 root root 4096 Dec 22 2021 .. -rw-r--r-- 1 root root 18970 Dec 2 2021 BUILDING.txt -rw-r--r-- 1 root root 6210 Dec 2 2021 CONTRIBUTING.md -rw-r--r-- 1 root root 57092 Dec 2 2021 LICENSE -rw-r--r-- 1 root root 2333 Dec 2 2021 NOTICE -rw-r--r-- 1 root root 3378 Dec 2 2021 README.md -rw-r--r-- 1 root root 6898 Dec 2 2021 RELEASE-NOTES -rw-r--r-- 1 root root 16507 Dec 2 2021 RUNNING.txt drwxr-xr-x 2 root root 4096 Dec 22 2021 bin drwxr-xr-x 1 root root 4096 Sep 1 04:38 conf drwxr-xr-x 2 root root 4096 Dec 22 2021 lib drwxrwxrwx 1 root root 4096 Sep 1 04:38 logs drwxr-xr-x 2 root root 4096 Dec 22 2021 native-jni-lib drwxrwxrwx 2 root root 4096 Dec 22 2021 temp drwxr-xr-x 2 root root 4096 Dec 22 2021 webapps drwxr-xr-x 7 root root 4096 Dec 2 2021 webapps.dist drwxrwxrwx 2 root root 4096 Dec 2 2021 work
-
tomcat中
webapps
文件夹为空, aliyun镜像默认选择最小的镜像, 保证可用即可;可以将webapps.dist
中的文件复制到webapps
中!root@a023804512d5:/usr/local/tomcat/webapps# ls root@a023804512d5:/usr/local/tomcat/webapps# cp -r ../webapps.dist/* . root@a023804512d5:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager managerroot@a023804512d5:/usr/local/tomcat/webapps# ls -al total 32 drwxr-xr-x 1 root root 4096 Sep 1 04:48 . drwxr-xr-x 1 root root 4096 Dec 22 2021 .. drwxr-xr-x 3 root root 4096 Sep 1 04:48 ROOT drwxr-xr-x 15 root root 4096 Sep 1 04:48 docs drwxr-xr-x 7 root root 4096 Sep 1 04:48 examples drwxr-xr-x 6 root root 4096 Sep 1 04:48 host-manager drwxr-xr-x 6 root root 4096 Sep 1 04:48 manager
4.2.3 安装ES+kibana
1) s安装 ES
-
启动容器, 直接
run
docker run -d --name elasticsearch -p 7003:9200 -p 7004:9300 -e "discovery.type=single-node" elasticsearch:7.6.2 # --net somenetwork: 网络配置 # es 的数据一般需要选择安全目录进行挂载
-
es比较耗内存,可以用过
docker status
查看CPU状态CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 7bcd4d1f4666 elasticsearch 0.24% 1.261GiB / 7.545GiB 16.71% 656B / 0B 0B / 696kB 45
-
浏览器打开:
{ "name": "7bcd4d1f4666", "cluster_name": "docker-cluster", "cluster_uuid": "8Kv987NsTrO-JKZKkhyiow", "version": { "number": "7.6.2", "build_flavor": "default", "build_type": "docker", "build_hash": "ef48eb35cf30adf4db14086e8aabd07ef6fb113f", "build_date": "2020-03-26T06:34:37.794943Z", "build_snapshot": false, "lucene_version": "8.4.0", "minimum_wire_compatibility_version": "6.8.0", "minimum_index_compatibility_version": "6.0.0-beta1" }, "tagline": "You Know, for Search" }
-
停止
elastic search
容器root@su-codeink: ~ # docker stop elasticsearch elasticsearch root@su-codeink: ~ # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-
增加对内存的限制
docker run -d --name es01 -p 7003:9200 -p 7004:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m" elasticsearch:7.6.2
2) 安装 Kibana
3) Kibana连接ES
4.3 可视化
portainer
docker run -d -p 7009:8000 -p 7010:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ee:latest
docker run -d -p 7010:9000 --restart=always -v \var\run\docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Rancher( CI / CD 使用)
4.4 容器数据卷
是什么?
问题: 删除容器,那容器中的数据也会随之删除!
解决:
docker数据卷:使得docker容器中的数据不仅可以在容器中, 还可以存储在主机中!即:容器数据共享, 将容器中产生的数据同步到本地.
实际上就等于, 将容器内的目录挂载到Linux上面.
有三种食用方式:
- 指定路径挂载
- 匿名挂载
- 具名挂载
- 镜像内部自己挂载的(可以通过
dockerfile
在创建自己的镜像时进行挂载配置)第二种,第三种方式均使用docker默认的挂载地址
/var/lib/docker/volume/xxx
4.4.1 指定路径挂载
-v命令
命令解释
docker run -it -v 主机目录:容器目录 -p
-
运行Ubuntu
root@su-codeink: /home # docker run -it -v /home/docker-test-v:/home ubuntu /bin/bash root@8fb553b6145c:/# ls bin boot dev etc home lib lib32 lib64 libx32 media mnt ...
-
查看运行信息
root@su-codeink: /home/docker-test-v # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS 8fb553b6145c ubuntu "/bin/bash" About a minute ago Up About a minute root@su-codeink: /home/docker-test-v # docker inspect 8fb553b6145c ... "Mounts": [ { "Type": "bind", "Source": "/home/docker-test-v", "Destination": "/home", "Mode": "", "RW": true, "Propagation": "rprivate" } ], ...
其中的
Source
是主机内的目录地址,Destination
则是docker容器内的目录地址 -
修改容器内文件
root@8fb553b6145c:/home# touch 111 root@8fb553b6145c:/home# echo 111 >> 111 root@8fb553b6145c:/home# echo hello-v >> 111 root@8fb553b6145c:/home# cat 111 111 hello-v
-
在主机内的被挂载目录查看
root@su-codeink: /home/docker-test-v # ls 111 root@su-codeink: /home/docker-test-v # cat 111 111 hello-v
同样,在主机内被挂载的目录修改, 容器内也会得到修改(不管是否重启)
root@su-codeink: /home/docker-test-v # vi 111 root@su-codeink: /home/docker-test-v # cat 111 111 hello-v this updated by host machine!
关闭容器后重新打开再看一下!
# 关闭容器后显示 root@su-codeink: /home # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES root@su-codeink: /home # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS 8fb553b6145c ubuntu "/bin/bash" 28 minutes ago Exited (0) 11 seconds ago # 启动容器 root@su-codeink: /home # docker start 8fb553b6145c 8fb553b6145c root@su-codeink: /home # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS 8fb553b6145c ubuntu "/bin/bash" 28 minutes ago Up 15 seconds # 进入容器 root@su-codeink: /home # docker attach 8fb553b6145c root@8fb553b6145c:/# cd home root@8fb553b6145c:/home# ls 111 root@8fb553b6145c:/home# cat 111 111 hello-v this updated by host machine!
-
优点
以后只需要在本地修改就好,容器会自动同步
4.4.2 实战MySQL
思考MySQL数据持久化的问题
-
启动
MySQL
, 查看官方(hub.docker.com)docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag -e: # mysql 的环境配置 root@su-codeink: /home # docker run -d -p 7001:3306 -v /home/docker-share/mysql/conf:/etc/mysql/conf.d -v /home/share/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql01 mysql:5.7 8f6d99dd227b16eac230ed64bb96b52e0797b14f69482df2a990d2ee9add3be4 -v: # 可以挂载多个
-
即使容器删掉,数据也不会丢失!
在MySQL中新建数据库、表,向表里插入数据。
将容器停掉并删除
docker stop 容器id
可以发现MySQL已经打不开了.删除容器后重新运行命令
# root@su-codeink: /home/docker-share/mysql/data # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES 2887ec5c2a89 mysql:5.7 "docker-entrypoint.s…" 16 minutes ago Up 16 minutes mysql01 # 停止并删除容器 root@su-codeink: /home/docker-share/mysql/data # docker stop 2887ec5c2a89 2887ec5c2a89 root@su-codeink: /home/docker-share/mysql/data # docker rm 2887ec5c2a89 2887ec5c2a89 # 重新运行 root@su-codeink: /home/share/mysql # docker run -d -p 7001:3306 -v /home/docker-share/mysql/conf:/etc/mysql/conf.d -v /home/docker-share/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql01 mysql:5.7 cc45bffba7fb09f1d2f0765babc284057c5202c63830a516385d2be33f30e882
可以发现数据未丢失
4.4.3 (具名/匿名)挂载
匿名挂载
匿名就是不写主机目录
eg.
docker run -d -P --name nginx01 -v /etc/nginx nginx
-
匿名挂载
root@su-codeink: /home/share/mysql # docker run -d -p 7001:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql02 mysql:5.7 f8da431d1802bf54fc9125f56e909d38adede387f08e24230c3da5464154e620 root@su-codeink: /home/share/mysql # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES f8da431d1802 mysql:5.7 "docker-…" 4 seconds ago Up 4 seconds mysql02 cc45bffba7fb mysql:5.7 "docker-…" 27 minutes ago Exited (0) 9 minutes ago mysql01
-
使用
volume
命令root@su-codeink: /home/share/mysql # docker volume list DRIVER VOLUME NAME local da43abb536cb441b2b9b634206b6828c83a5201469490c61daf79fc430c43030 local e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da local f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b local fe841c8b25f5f1676a9790d8b4f3112236cf078bfad679d7c7ae6e7ded951efa local portainer_data local varrundocker.sock
-
使用
inspect
命令"Mounts": [ { "Type": "volume", "Name": "e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da", "Source": "/var/lib/docker/volumes/e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da/_data", "Destination": "/etc/mysql/conf.d", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b", "Source": "/var/lib/docker/volumes/f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b/_data", "Destination": "/var/lib/mysql", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ]
##### 具名挂载
> `-v vname 容器内需要挂载的目录地址 `
- 具名挂载运行
```shell
root@su-codeink: /home/share/mysql # docker run -d -p 7002:3306 -v mysql03-conf:/etc/mysql/conf.d -v mysql03.data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wqbssy1314. --name mysql03 mysql:5.7
87d3524c75281259bddd59412b0e929c3702b57d3a460768643339bb230ccfb5
-v mysql03.conf:xxx: 就是具名挂载
root@su-codeink: /home/share/mysql # docker volume list
DRIVER VOLUME NAME
local 14d827baaa98e8491f5085a4562ea55b5d2b8465acf3d0a80509206e6daae34a
local bc1bf4578166c5aabf5134e29ceb48fc79c3537dfcc8ac5b532098d35ae85465
local da43abb536cb441b2b9b634206b6828c83a5201469490c61daf79fc430c43030
local e2e7c8f67d401ec74ae7b4229d14965354f9649896b8168ba8b6ce541a9646da
local f59fcf0a5e11ffca782555f993160b5bd509fbff6ad80f668d169bbd2976836b
local fe841c8b25f5f1676a9790d8b4f3112236cf078bfad679d7c7ae6e7ded951efa
local mysql03-conf
local mysql03.data
local portainer_data
local varrundocker.sock
root@su-codeink: /home/share/mysql # docker volume inspect mysql03.data
[
{
"CreatedAt": "2022-09-02T12:32:08+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mysql03.data/_data",
"Name": "mysql03.data",
"Options": null,
"Scope": "local"
}
]
在docker里, 所有的数据卷在没有指定目录的情况下都是在/var/lib/docker/volumes/xxx
下
4.4.4 容器数据共享
可以用于多个容器同步数据
比较不同:
docker run -it --name u01 -v /home/docker-share/u01:/u01 ubuntu
docker run -it --name u02 -v u02-v:/u01 --volumes-from u01 ubuntu
# 这样做不对!, 因为容器内挂载的重名了, 会以u02-v为数据卷名字在docker的volumes目录生成一个新的volume
docker run -it --name u03 --volumes-from u01 ubuntu
u01中 Mounts
"Mounts": [
{
"Type": "bind",
"Source": "/home/docker-share/u01",
"Destination": "/u01",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
u02中 Mounts
"Mounts": [
{
"Type": "volume",
"Name": "u02-v",
"Source": "/var/lib/docker/volumes/u02-v/_data",
"Destination": "/u01",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]
u03中 Mounts
"Mounts": [
{
"Type": "bind",
"Source": "/home/docker-share/u01",
"Destination": "/u01",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
通过
--volumes-from
进行挂载时, 不需要用- v
指定共享目录, 如果使用-v
指定的路径与--volumes-from
中挂载的相同,则会以-v
为准

容器之间配置信息的传递通过数据卷进行,数据卷容器的生命周期一直持续到没有容器使用为止.
但是一旦持久化到本地,本地的数据是不会(因停止容器或者删除容器)删除的
4.5 DockerFile
DockerFile 就是用来构建docker镜像的构建文件
镜像是一层层的, 脚本中就用一个个命令来对应, 每个命令都是一层
4.5.1 基本知识
步骤:
- 编写一个dockerfile文件
- docker build 构建成为镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub, 阿里云镜像仓库)
了解Ubuntu
的dockerfile
FROM scratch
ADD ubuntu-bionic-oci-amd64-root.tar.gz /
CMD ["bash"]
了解CentOS
的dockerfile
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
-
FROM
: 最基本的镜像,docker hub中99%的镜像都是从scrach
过来的. -
每个指令(关键字) 都必须是大写字母
-
顺序执行
-
每个指令都会创建提交一个新的镜像层, 并提交
很多官方镜像都是基础包, 很多功能没有, 我们通常会写自己的镜像!
dockerfile是面向开发的, 我们以后要发布项目, 做镜像就需要编写dockerfile文件
4.5.2 Dockerfile 指令
部分 | 命令 |
---|---|
基础镜像信息 | FROM |
维护者信息 | MAINTAINER |
镜像操作指令 | RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器启动时执行指令 | CMD、ENTRYPOINT |
- FROM:指定base镜像,Dockerfile中第一条指令必须是
FROM
指令,其格式如下: - MAINTAINER(弃用):指明作者信息,格式为:
- RUN:在镜像的构建过程中执行特定的命令,并生成一个中间镜像。比如安装一些软件、配置一些基础环境,可使用\来换行
- COPY: 将主机内的文件复制到镜像内, 如果目的位置不存在, Docker为自动创建所有需要的目录结构, 但是它只是简单的复制, 并不会去做文件提取和解压工作
- ADD: 构建镜像时, 复制上下文中的文件到镜像内
- EXPOSE: 为构建的镜像设置监听端口
- ENV: 在构建的镜像中设置环境变量
- LABEL: 给构建的镜像打标签
- VOLUME: 指定镜像内的目录为数据卷
- USER: 为接下来的Dockerfile指令指定用户. 受影响的指令有:RUN,CMD、ENTRYPOINT
- WORKDIR: 为接下来的Dockerfile指令指定当前工作目录,可多次使用,如果使用的是相对路径,则相对的是上一个工作目录,类似于shell中的
cd
命令 - ARG: 指定用户在docker build --build-arg
= 时可以使用的参数 - ONBUILD: 向镜像中添加一个触发器, 当以该镜像为基础镜像再次构建新的镜像时, 会触发执行其中的指令
- STOPSIGNAL: 触发系统信号
- ENTRYPOINT: 指定镜像的执行程序
- CMD: 指定容器运行时的默认参数
CMD vs ENTRYPOINT
- CMD: 指定这个容器启动时需要运行的命令, 只有最后一个会(在启动容器时)生效, 可被替代
- ENTRYPOINT: 指定这个容器时需要运行的命令, 可以追加命令
CMD
root@su-codeink: /home/dockerfile $ vim dockerfile-cmd-test
root@su-codeink: /home/dockerfile $ cat dockerfile-cmd-test
FROM centos
CMD ["ls","-al"]
root@su-codeink: /home/dockerfile $ docker build -f dockerfile-cmd-test -t cmd-test .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : CMD ["ls","-al"]
---> Running in 15d29b17608a
Removing intermediate container 15d29b17608a
---> 8715c287b7f6
Successfully built 8715c287b7f6
Successfully tagged cmd-test:latest
可以看到镜像已经成功创建
root@su-codeink: /home/dockerfile $ docker run -it cmd-test
total 56
drwxr-xr-x 1 root root 4096 Sep 2 10:49 .
drwxr-xr-x 1 root root 4096 Sep 2 10:49 ..
-rwxr-xr-x 1 root root 0 Sep 2 10:49 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Sep 2 10:49 dev
drwxr-xr-x 1 root root 4096 Sep 2 10:49 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 131 root root 0 Sep 2 10:49 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Aug 27 02:25 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
root@su-codeink: /home/dockerfile $ docker run -it cmd-test -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
root@su-codeink: /home/dockerfile $ docker run -it cmd-test ls -a
. .dockerenv dev home lib64 media opt root sbin sys usr
.. bin etc lib lost+found mnt proc run srv tmp var
ENTRYPOINT
$ cat dockerfile-entrypoint-test
FROM centos
ENTRYPOINT ["ls","-a"]
$ docker build -f dockerfile-entrypoint-test -t entrypoint-test .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in ce3cb4b0eafe
Removing intermediate container ce3cb4b0eafe
---> af63a086f9c2
Successfully built af63a086f9c2
Successfully tagged entrypoint-test:latest
root@su-codeink: /home/dockerfile $ docker run -it entrypoint-test
. .dockerenv dev home lib64 media opt root sbin sys usr
.. bin etc lib lost+found mnt proc run srv tmp var
root@su-codeink: /home/dockerfile $ docker run -it entrypoint-test -al
total 56
drwxr-xr-x 1 root root 4096 Sep 2 10:53 .
drwxr-xr-x 1 root root 4096 Sep 2 10:53 ..
-rwxr-xr-x 1 root root 0 Sep 2 10:53 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Sep 2 10:53 dev
drwxr-xr-x 1 root root 4096 Sep 2 10:53 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 135 root root 0 Sep 2 10:53 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Aug 27 02:25 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
4.5.3 实战 创建Linux镜像
-
编写DockerFile文件
root@su-codeink: /home/dockerfile $ vim codeink-ubuntu root@su-codeink: /home/dockerfile $ cat codeink-ubuntu FROM ubuntu MAINTAINER codeink<111> ENV MYPATH /home WORKDIR $MYPATH RUN apt-get update RUN apt-get install -y apt-utils RUN apt-get install -y vim RUN apt-get install -y net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "-----end-----" CMD /bin/bash $ docker build -f codeink-ubuntu -t codeink-ubuntu .
-
查看已经创建好的镜像
root@su-codeink: ~ $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE codeink-ubuntu latest bea813b92920 53 minutes ago 184MB tomcat 9.0 b8e65a4d736d 8 months ago 680MB tomcat latest fb5657adc892 8 months ago 680MB redis latest 7614ae9453d1 8 months ago 113MB nginx stable 50fe74b50e0d 8 months ago 141MB mysql 5.7 c20987f18b13 8 months ago 448MB mysql latest 3218b38490ce 8 months ago 516MB portainer/portainer-ce latest 0df02179156a 8 months ago 273MB ubuntu latest ba6acccedd29 10 months ago 72.8MB hello-world latest feb5d9fea6a5 11 months ago 13.3kB portainer/portainer latest 580c0e4e98b0 17 months ago 79.1MB kibana 7.6.2 f70986bc5191 2 years ago 1.01GB elasticsearch 7.6.2 f29a1ee41030 2 years ago 791MB
可以看到镜像已经创建完成, 使用该镜像创建容器
docker run -it --name xxx codeink-ubuntu
-
启动并进入使用自定义镜像创建的容器
可以看到vim已经成功安装!
-
查看镜像构建的过程
root@su-codeink: ~ $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE codeink-ubuntu latest bea813b92920 41 minutes ago 184MB tomcat 9.0 b8e65a4d736d 8 months ago 680MB tomcat latest fb5657adc892 8 months ago 680MB redis latest 7614ae9453d1 8 months ago 113MB nginx stable 50fe74b50e0d 8 months ago 141MB mysql 5.7 c20987f18b13 8 months ago 448MB mysql latest 3218b38490ce 8 months ago 516MB portainer/portainer-ce latest 0df02179156a 8 months ago 273MB ubuntu latest ba6acccedd29 10 months ago 72.8MB hello-world latest feb5d9fea6a5 11 months ago 13.3kB portainer/portainer latest 580c0e4e98b0 17 months ago 79.1MB kibana 7.6.2 f70986bc5191 2 years ago 1.01GB elasticsearch 7.6.2 f29a1ee41030 2 years ago 791MB root@su-codeink: ~ $ docker history bea813b92920 IMAGE CREATED CREATED BY SIZE bea813b92920 41 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B fa1ecb17e31a 41 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B 88050887246c 41 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B f6a088c78641 41 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B 3294228b2aaa 41 minutes ago /bin/sh -c apt-get install -y vim 68.2MB 28137b9119fc 42 minutes ago /bin/sh -c apt-get install -y apt-utils 5.15MB 0b8aa9d045f9 42 minutes ago /bin/sh -c apt-get update -y 37.8MB 1d325a7a75f0 44 minutes ago /bin/sh -c #(nop) WORKDIR /home 0B 122e22102dda 44 minutes ago /bin/sh -c #(nop) ENV MYPATH=/home 0B 3e1ebaa6c42e 44 minutes ago /bin/sh -c #(nop) MAINTAINER codeink<111> 0B ba6acccedd29 10 months ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 10 months ago /bin/sh -c #(nop) ADD file:5d68d27cc15a80653… 72.8MB
4.5.4 实战 Tomcat
-
准备tomcat压缩包、JDK的压缩包
-
编写Dockerfile
FROM centos COPY README.md /usr/local/README.md ADD jdk-8u202-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.65.tar.gz /usr/local RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOMR /usr/local/jdk1.8.0_202 ENV CLASSPATH $JAVA_HOME/lib/dt.jar;$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.65 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.65 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib;$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.65/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.65/logs/catalina.out
-
启动容器
root@su-codeink: /data/file $ docker run -p 7001:8080 --name codeink-tomcat-test -v /home/docker-share/tomcat-test/webapps/test:/usr/local/apache-tomcat-9.0.65/webapps/test -v /home/docker-share/tomcat-test/logs:/usr/local/apache-tomcat-9.0.65/logs codeink-tomcat
-
在被挂载的目录中进行编写
-
创建
WEB-INFO
文件夹, 并创建web.xml文件<?xml version="1.0" encoding="gb2312"?> <web-app> <display-name>My Web Application</display-name> <description> An application for test. </description> </web-app>
-
编写index.jsp/index.html/或者其他主界面文件
<html> <body> <center>Now time is: <%=new java.util.Date()%></center> </body> </html>
-
-
查看是否成功
4.5.5 挂载Volume
# 向一个dockerfile文件中写入下列指令
FROM ubuntu
VOLUME ["V01", "V02"]
CMD echo "====end===="
CMD /bin/bash
# 运行docker build 指令生成镜像
通过这种方式可以直接用镜像挂载
可用看到镜像已经生成成功!
使用自己的镜像创建一个容器
root@su-codeink: /home/test # docker run -it codeink/ubuntu:0.0.1 /bin/bash
root@095f73778e7c:/# ls
V01 V02 bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
# 其中的 V01、V02 就是我们在dockerfile文件中写的,也就是在生成容器的时候会自动挂载的数据卷目录
docker inspect xxx
# 使用inspect命令可以看到容器的详细信息,在Mounts中可以看到被挂载的目录信息
"Mounts": [
{
"Type": "volume",
"Name": "cbcfd09ded67c841d4f21a5a0b0b453c6e83dde544526495df155454abbdd7fd",
"Source": "/var/lib/docker/volumes/cbcfd09ded67c841d4f21a5a0b0b453c6e83dde544526495df155454abbdd7fd/_data",
"Destination": "V01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "36cd4342800b826a4cb9546ac63d7816b61350a897a67633f063be7c77f47952",
"Source": "/var/lib/docker/volumes/36cd4342800b826a4cb9546ac63d7816b61350a897a67633f063be7c77f47952/_data",
"Destination": "V02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
4.6 发布镜像
可以在DockerHub进行发布!(需要注册账号)
直接docker login
可以使用docker tag 镜像id 修改后的tag
之后docker push 即可
可以在阿里云镜像服务
- 登录阿里云
- 找到容器镜像服务
- 创建命名空间
- 创建容器镜像
- 根据手册进行
5. Docker网络
5.1 Docker网络理解
三个网卡:
- lo: 本机回环地址
- etho: 服务器内网地址
- docker0: docker0地址
docker 如何处理web访问
-
运行一个centos,一个tomcat
在centos中可以直接使用
ip addr
查看容器内网卡地址[root@4899a710ced0 /]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 180: eth0@if181: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
在tomcat(基于Debian系统),直接使用
docker inspect 容器id
即可查看容器IP地址"Networks": { "bridge": { "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } }
可以在tomcat容器内安装一下
net-tools
,就可以shi用ipconfig 命令
查看完整信息:# 首先需要将apt-get更新一下 root@4132cfda09a8:/etc/apt# apt-get update # 安装一下net-tools工具 root@4132cfda09a8:/etc/apt# apt-get install net-tools # 使用net-tools查看tomcat容器的网络配置 root@4132cfda09a8:/etc/apt# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 1315 bytes 18068129 (17.2 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1305 bytes 100601 (98.2 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
可以看到在容器tomcat内,其IP是
172.17.0.2
, 而centos内的ip有个为172.17.0.3
, 可以发现docker会给每个容器分配一个IP地址;此时再次查看主机的IP地址, 可以发现ip地址从3个变为了5个.root@su-codeink: ~ $ ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 52:54:00:42:43:42 brd ff:ff:ff:ff:ff:ff inet 10.0.4.6/22 brd 10.0.7.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe42:4342/64 scope link valid_lft forever preferred_lft forever 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ad:a7:d5:2d brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:adff:fea7:d52d/64 scope link valid_lft forever preferred_lft forever 177: vethd6c8b73@if176: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 06:c1:1e:3d:a3:50 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::4c1:1eff:fe3d:a350/64 scope link valid_lft forever preferred_lft forever 181: vethab4cbe1@if180: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether ba:70:ed:5d:29:fb brd ff:ff:ff:ff:ff:ff link-netnsid 1 inet6 fe80::b870:edff:fe5d:29fb/64 scope link valid_lft forever preferred_lft forever
docker使用的技术是
evth-pair
技术, 在177和181两个ip地址信息中可以看到177
中显示了@if176
,181
中显示了@if180
,evth-pair
evth-pair就是一对的虚拟设备接口, 一段连着协议、一段彼此相连,
OpenStac和Docker容器之间的连接、OVS的连接都是使用evth-pair技术
可以测试一下 centos中是否可以ping通tomcat!
可以ping通

Docker 使用的是Linux的桥接, 宿主机中是一个Docker的网桥Docker0, Docker中所有的网络接口都是虚拟的.只要容器删除, 对应的一对网桥ip就没了.

5.2 实战 --link
场景:在微服务中在连接数据时, 根据ip找到数据库地址, 但如果容器ip换掉了, 能否仅通过名字来访问容器?
root@su-codeink: ~ $ docker run -it --name centos-01 centos
root@su-codeink: ~ $ docker run -it --name centos-02 centos
root@su-codeink: ~ $ docker run -it --name centos-03 --link centos-02 centos
root@su-codeink: ~ $ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5cce9f5fe1c4 centos "/bin/bash" 21 seconds ago Up 20 seconds centos-03
f43e5011363e centos "/bin/bash" 42 seconds ago Up 41 seconds centos-01
40303cdff6e3 centos "/bin/bash" 53 seconds ago Up 52 seconds centos-02
root@su-codeink: ~ $
对结果进行查看:
root@su-codeink: ~ $ docker exec -it centos-01 ping centos-02
ping: centos-02: Name or service not known
root@su-codeink: ~ $ docker exec -it centos-03 ping centos-02
PING centos-02 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos-02 (172.17.0.2): icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from centos-02 (172.17.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from centos-02 (172.17.0.2): icmp_seq=3 ttl=64 time=0.060 ms
root@su-codeink: ~ $ docker exec -it centos-02 ping centos-03
ping: centos-03: Name or service not known
可以发现, 只有centos03
可以ping通centos02
, 其他都无法ping通, 就算centos02
也无法ping通centos03
!
对结果分析:
-
使用
docker network ls
查看所有网络 -
使用
docker network inspect 网络id
"Containers": {
"40303cdff6e3f9d43ab4afecefd05b241b4ccf35f4a6d9a6ac6a7b682743bd5a": {
"Name": "centos-02",
"EndpointID": "da04fe700e7ba8954e294bb8465e667ce1cc8750fb4b338e88eb0bd60312792d",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"5cce9f5fe1c4d56db171e79c31db1d50203b8a296ed7f891081a6ba909c3466b": {
"Name": "centos-03",
"EndpointID": "d80d64c81f13ebbde21e1cde57be49b58f31f9e5c3900e1d0d091461ac8e26ff",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"f43e5011363e15e300c6f45231d06089fca1f2aaa7ada0924e92787729943412": {
"Name": "centos-01",
"EndpointID": "87db19d95a1dbd32a85425844d8ecdabde26a9f7c62f5eee1500f244181f1b3d",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
}
使用docker inspect 容器id
, 可以看到一个参数Links
"Links": [
"/centos-02:/centos-03/centos-02"
],
但是, 已经不推荐使用了!
原因:docker0不支持容器名连接访问, 现在改为使用自定义网络
5.3 自定义网络
查看所有的docker网络docker network ls
网络模式:
- bridge: 桥接 Docker 默认
- none: 不配置网络
- host: 和宿主机共享网络
- container: 容器网络连通(局限大)
测试
--net: 指定网络模式
docker0特点: 默认, 容器名不能访问, --link 可以打通连接
创建自己的网络:
root@su-codeink: ~ $ docker network create --driver bridge --subnet 192.168.100.0/24 --gateway 192.168.100.254 codeink-net
0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6
root@su-codeink: ~ $ docker network ls
NETWORK ID NAME DRIVER SCOPE
8f746dac50cd bridge bridge local
0332f225e381 codeink-net bridge local
90f64b2d0c7f host host local
ca05d4e43d85 none null local
root@su-codeink: ~ $ docker network inspect codeink-net
[
{
"Name": "codeink-net",
"Id": "0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6",
"Created": "2022-09-05T18:45:19.3457286+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.100.0/24",
"Gateway": "192.168.100.254"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
使用自定义网络运行容器
$ docker run -d -P --name codeink-tomcat-01 codeink/tomcat
$ docker run -d -P --name codeink-tomcat-02 codeink/tomcat
$ docker run -d -P --name codeink-tomcat-03 --net codeink-net codeink/tomcat
$ docker run -d -P --name codeink-tomcat-04 --net codeink-net codeink/tomcat
$ docker exec -it codeink-tomcat-04 ping codeink-tomcat-03
PING codeink-tomcat-03 (192.168.100.1) 56(84) bytes of data.
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=2 ttl=64 time=0.058 ms
$ docker exec -it codeink-tomcat-04 ping 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 192.168.100.2: icmp_seq=2 ttl=64 time=0.034 ms
$ docker exec -it codeink-tomcat-04 ping 192.168.100.1
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=64 time=0.052 ms
$ docker exec -it codeink-tomcat-04 ping codeink-tomcat-01
ping: codeink-tomcat-01: Name or service not known
$ docker exec -it codeink-tomcat-04 ping codeink-tomcat-02
即: 使用自定义网络时,不使用--link也可以直接使用容器名ping
通均使用该自定义网络的容器, 但是还是不能直接使用容器名ping
通没使用该网络的容器!
好处:
不同的集群使用不同的网络, 保证集群是安全和健康的
5.4 网络连通
使用
docker network connect
!!!
$ docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
使用该命令后, 就是将该容器放到了该网络中
$ docker network inspect codeink-net
[
{
"Name": "codeink-net",
"Id": "0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6",
"Created": "2022-09-05T18:45:19.3457286+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.100.0/24",
"Gateway": "192.168.100.254"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"0ca324544f101ee899fe7a1eef12c7697468e6b7eded52a3d5b61d4a4f4bc42e": {
"Name": "codeink-tomcat-04",
"EndpointID": "580d4d96f7f0d457b0d80aa6b00825f2b4518be01c315fc33cd0cbcfd2226c0c",
"MacAddress": "02:42:c0:a8:64:02",
"IPv4Address": "192.168.100.2/24",
"IPv6Address": ""
},
"55832c4673b60b72b84b63a727bca63fdab0c787d14360cb2ed6be7201674ae1": {
"Name": "codeink-tomcat-01",
"EndpointID": "a8dc21b35b2c4585938afc0c58ba10a4f7a6fe9c2c9e8ebb9fdabb8866ed640e",
"MacAddress": "02:42:c0:a8:64:03",
"IPv4Address": "192.168.100.3/24",
"IPv6Address": ""
},
"e9bdf9a8d68822963bc38c7931051770712c84b60ecc445a0c34a6dfbd47feff": {
"Name": "codeink-tomcat-03",
"EndpointID": "bf26f78cebd7401396064e36bf4eeeef20b8afe5077b21a4ca109609114dbfaf",
"MacAddress": "02:42:c0:a8:64:01",
"IPv4Address": "192.168.100.1/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
$ docker inspect codeink-tomcat-01
...
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "8f746dac50cd1aed398b87909d5b9ba7a943e1e0ec72a5f98f96485a7bc580c8",
"EndpointID": "b93c157537d2ddd1a9f92f5ecf958ff7ed346f0a558f1f2e866f0ba6a5dfd71f",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
},
"codeink-net": {
"IPAMConfig": {},
"Links": null,
"Aliases": [
"55832c4673b6"
],
"NetworkID": "0332f225e381fc3d686fa1c283a40d6c3e8638bf67ffcb90a1ecb770f33e2bc6",
"EndpointID": "a8dc21b35b2c4585938afc0c58ba10a4f7a6fe9c2c9e8ebb9fdabb8866ed640e",
"Gateway": "192.168.100.254",
"IPAddress": "192.168.100.3",
"IPPrefixLen": 24,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a8:64:03",
"DriverOpts": {}
}
}
...
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
8f746dac50cd bridge bridge local
0332f225e381 codeink-net bridge local
90f64b2d0c7f host host local
ca05d4e43d85 none null local
$ docker network connect codeink-net codeink-tomcat-01
$ docker exec -it codeink-tomcat-01 ping codeink-tomcat-03
PING codeink-tomcat-03 (192.168.100.1) 56(84) bytes of data.
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from codeink-tomcat-03.codeink-net (192.168.100.1): icmp_seq=2 ttl=64 time=0.056 ms
5.5 实战:redis集群部署
-
创建网卡
docker network create redis # 可以 docker network inspect redis
-
编写
Shell
脚本, 生成redis配置文件
for port in $(seq 1 6);
do
mkdir -p /data/redis/node-${port}/conf
touch /data/redis/node-${port}/conf/redis.conf
cat <<EOF >/data/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.100.100.${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
其中的 cluster-announce-ip
是创建好的网卡的网络中的ip,
- 编写shell,一键启动redis
for port in $(seq 1 6);
do
docker run -p 700${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /data/redis/node-${port}/data:/data \
-v /data/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.100.100.${port} redis:5.0 redis-server /etc/redis/redis.conf;
done
- 查看redis启动情况
- 创建集群
docker exec -it redis-1 /bin/sh;
redis-cli --cluster create cat redis-cluster-ip.list | while read line
do
eval "$line"
echo -n "172.100.100.$port:6378 "
done
redis-cli --cluster create 172.100.100.1:6379 172.100.100.2:6379 172.100.100.3:6379 172.100.100.4:6379 172.100.100.5:6379 172.100.100.6:6379 --cluster-replicas 1
$ redis-cli --cluster create 172.100.100.1:6379 172.100.100.2:6379 \
172.100.100.3:6379 172.100.100.4:6379 172.100.100.5:6379 \
172.100.100.6:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.100.100.5:6379 to 172.100.100.1:6379
Adding replica 172.100.100.6:6379 to 172.100.100.2:6379
Adding replica 172.100.100.4:6379 to 172.100.100.3:6379
M: 502f6862c4c88d797426cd4b786ce6bd5c3be17a 172.100.100.1:6379
slots:[0-5460] (5461 slots) master
M: 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 172.100.100.2:6379
slots:[5461-10922] (5462 slots) master
M: 74e1e8a2f97673d33f45c4a124a630963ccaf83b 172.100.100.3:6379
slots:[10923-16383] (5461 slots) master
S: d176a1ef844f455b11dd5bc82e504666a0ec1215 172.100.100.4:6379
replicates 74e1e8a2f97673d33f45c4a124a630963ccaf83b
S: 1c041167447f10379c8d9d74baa3c7c866184994 172.100.100.5:6379
replicates 502f6862c4c88d797426cd4b786ce6bd5c3be17a
S: 7de6f4f57d7536720656265b49dd27752cae99b9 172.100.100.6:6379
replicates 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 172.100.100.1:6379)
M: 502f6862c4c88d797426cd4b786ce6bd5c3be17a 172.100.100.1:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 7de6f4f57d7536720656265b49dd27752cae99b9 172.100.100.6:6379
slots: (0 slots) slave
replicates 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9
M: 74e1e8a2f97673d33f45c4a124a630963ccaf83b 172.100.100.3:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 172.100.100.2:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 1c041167447f10379c8d9d74baa3c7c866184994 172.100.100.5:6379
slots: (0 slots) slave
replicates 502f6862c4c88d797426cd4b786ce6bd5c3be17a
S: d176a1ef844f455b11dd5bc82e504666a0ec1215 172.100.100.4:6379
slots: (0 slots) slave
replicates 74e1e8a2f97673d33f45c4a124a630963ccaf83b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# 使用集群方式
$ redis-cli -c
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:338
cluster_stats_messages_pong_sent:343
cluster_stats_messages_sent:681
cluster_stats_messages_ping_received:338
cluster_stats_messages_pong_received:338
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:681
127.0.0.1:6379> cluster nodes
7de6f4f57d7536720656265b49dd27752cae99b9 172.100.100.6:6379@16379 slave 1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 0 1662429755000 6 connected
74e1e8a2f97673d33f45c4a124a630963ccaf83b 172.100.100.3:6379@16379 master - 0 1662429755817 3 connected 10923-16383
1eb282e642d33bc6cf8d03d608c28bc2a31b34c9 172.100.100.2:6379@16379 master - 0 1662429754000 2 connected 5461-10922
502f6862c4c88d797426cd4b786ce6bd5c3be17a 172.100.100.1:6379@16379 myself,master - 0 1662429754000 1 connected 0-5460
1c041167447f10379c8d9d74baa3c7c866184994 172.100.100.5:6379@16379 slave 502f6862c4c88d797426cd4b786ce6bd5c3be17a 0 1662429755000 5 connected
d176a1ef844f455b11dd5bc82e504666a0ec1215 172.100.100.4:6379@16379 slave 74e1e8a2f97673d33f45c4a124a630963ccaf83b 0 1662429754013 4 connected
127.0.0.1:6379>
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.100.100.3:6379
OK
172.100.100.3:6379> get a
"b"
可以看到在node3中进行set a b, 为验证其高可用,将其关闭再试, 能够发现还可以找到!
$ redis-cli -c
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.100.100.4:6379
"b"
docker 搭建redis集群完成!
6. Docker进阶
6.1 Docker Compose
不使用Docker Compose的情况:
- DockerFile build run 手动操作 --> 单个容器
- 在微服务场景需要多次手动运行 --> 管理麻烦!
可以使用DockerCompose进行管理容器, 定义+运行 多个容器
官方描述
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.
使用场景
Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.
三步
Using Compose is basically a three-step process:
- Define your app’s environment with a
Dockerfile
so it can be reproduced anywhere.- Define the services that make up your app in
docker-compose.yml
so they can be run together in an isolated environment.- Run
docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively rundocker-compose up
using Compose standalone(docker-compose
binary).
6.1.1 作用
将多个容器编排, 单机场景!
一个docker-compose.yml
内容如下:
version: "3.9" # optional since v1.27.0
services:
web:
build: .
ports:
- "8000:5000"
volumes:
- .:/code
- logvolume01:/var/log
depends_on:
- redis
redis:
image: redis
volumes:
logvolume01: {}
6.1.2 安装
$ yum install -y docker-compose-plugin
$ docker compose version
Docker Compose version v2.10.2
6.1.3 Hi Compose
Docker 镜像 run --> 容器
DockerFile 构建镜像 --> 服务打包
docker-compose 启动项目(组合多个微服务/环境)
Docker 网络
6.1.4 yml语法
三层规则
1: version --> 版本
2: services --> 服务
服务1: web
images
build
network
ports
3: 其它!()
depends_on: 依赖的顺序!
6.2 Swarm集群
暂未学习,直接进入kubernetes的学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!