39-docker(一)

2020-07-07  本文已影响0人  Liang_JC

本章内容

◆ Docker简介
◆ Docker 镜像与制作
◆ Docker 数据管理
◆ Docker 网络
◆ Docker 仓库之单机 Docker Registry
◆ docker 仓库之分布式 Harbor
◆ 单机编排之 Docker Compose
◆ 补充-资源限制

一: 简介

1.1: docker 简介

1.1.1: Docker 是什么
1.1.2: Docker 的组成

https://docs.docker.com/engine/docker-overview/
Docker 主机(Host): 一个物理机或虚拟机,用于运行 Docker 服务进程和容器。
Docker 服务端(Server): Docker 守护进程, 运行 docker 容器。
Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用 docker API。
Docker 仓库(Registry): 保存镜像的仓库,类似于 git 或 svn 这样的版本控制系
Docker 镜像(Images): 镜像可以理解为创建实例使用的模板。
Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务。
官方仓库: https://hub.docker.com/

1.1.3: Docker 对比虚拟机

资源利用率更高: 一台物理机可以运行数百个容器,但是一般只能运行数十个虚拟机。
开销更小: 不需要启动单独的虚拟机占用硬件资源。
启动速度更快: 可以在数秒内完成启动。

使用虚拟机是为了更好的实现服务运行环境隔离, 每个虚拟机都有独立的内核,虚拟化可以实现不同操作系统的虚拟机,但是通常一个虚拟机只运行一个服务, 很明显资源利用率比较低且造成不必要的性能损耗, 我们创建虚拟机的目的是为了运行应用程序,比如 Nginx、 PHP、 Tomcat 等 web 程序, 使用虚拟机无疑带来了一些不必要的资源开销,但是容器技术则基于减少中间运行环节带来较大的性能提升

多个容器带来的以下问题怎么解决:
1.怎么样保证每个容器都有不同的文件系统并且能互不影响?
2.一个 docker 主进程内的各个容器都是其子进程,那么实现同一个主进程下不同类型的子进程? 各个进程间通信能相互访问(内存数据)吗?
3.每个容器怎么解决 IP 及端口分配的问题?
4.多个容器的主机名能一样吗?
5.每个容器都要不要有 root 用户?怎么解决账户重名问题?
以上问题怎么解决?

1.1.4: Linux Namespace 技术

namespace 是 Linux 系统的底层概念, 在内核层实现,即有一些不同类型的命名空间被部署在核内, 各个 docker 容器运行在同一个 docker 主进程并且共用同一个宿主机系统内核,各 docker 容器运行在宿主机的用户空间, 每个容器都要有类似于虚拟机一样的相互隔离的运行空间, 但是容器技术是在一个进程内实现运行指定服务的运行环境, 并且还可以保护宿主机内核不受其他进程的干扰和影响, 如文件系统空间、网络空间、进程空间等,目前主要通过以下技术实现

容器运行空间的相互隔离:

隔离类型 功能 系统调用参数 内核版本
MNT Namespace(mount) 提供磁盘挂载点和文件系统的隔离能力 CLONE_NEWNS Linux 2.4.19
IPC Namespace(Inter-Process Communication) 提供进程间通信的隔离能力 CLONE_NEWIPC Linux 2.6.19
UTS Namespace(UNIX Timesharing System) 提供主机名隔离能力 CLONE_NEWUTS Linux 2.6.19
PID Namespace(Process Identification) 提供进程隔离能力 CLONE_NEWPID Linux 2.6.24
Net Namespace(network) 提供网络隔离能力 CLONE_NEWNET Linux 2.6.29
User Namespace(user) 提供用户隔离能力 CLONE_NEWUSER Linux 3.8

1.1.4.1: MNT Namespace

每个容器都要有独立的根文件系统有独立的用户空间, 以实现在容器里面启动服务并且使用容器的运行环境,即一个宿主机是 ubuntu 的服务器,可以在里面启动一个 centos 运行环境的容器并且在容器里面启动一个 Nginx 服务,此 Nginx运行时使用的运行环境就是 centos 系统目录的运行环境, 但是在容器里面是不能访问宿主机的资源, 宿主机是使用了 chroot 技术把容器锁定到一个指定的运行目录里面。

例如: /var/lib/containerd/io.containerd.runtime.v1.linux/moby/容器 ID

启动三个容器用于以下验证过程:

Server: Docker Engine - Community
Engine:
Version: 18.09.7
API version: 1.39 (minimum version 1.12)
Go version: go1.10.8
Git commit: 2d0083d
Built: Thu Jun 27 17:26:28 2019
OS/Arch: linux/amd64
Experimental: false
# docker run -d --name nginx-1 -p 80:80 nginx
# docker run -d --name nginx-2 -p 81:80 nginx
# docker run -d --name nginx-3 -p 82:80 nginx

Debian 系统安装基础命令

# apt update
# apt install procps (top 命令)
# apt install iputils-ping (ping 命令)
# apt install net-tools (网络工具)

验证容器的根文件系统

image.png

1.1.4.2: IPC Namespace

一个容器内的进程间通信, 允许一个容器内的不同进程的(内存、 缓存等)数据访问,但是不能夸容器访问其他容器的数据。

1.1.4.3: UTS Namespace

UTS namespace(UNIX Timesharing System 包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识, 其中包含了 hostname 和域名domainname , 它使得一个容器拥有属于自己 hostname 标识,这个主机名标识独立于宿主机系统和其上的其他容器。

image.png

1.1.4.4: PID Namespace

Linux 系统中,有一个 PID 为 1 的进程(init/systemd)是其他所有进程的父进程, 那么在每个容器内也要有一个父进程来管理其下属的子进程, 那么多个容器的进程通 PID namespace 进程隔离(比如 PID 编号重复、 器内的主进程生成与回收子进程等)。
例如:下图是在一个容器内使用 top 命令看到的 PID 为 1 的进程是 nginx:

image.png

容器内的 Nginx 主进程与工作进程:

image.png

那么宿主机的 PID 究竟与容器内的 PID 是什么关系?

容器 PID 追踪:

1.1.4.4.1: 查看宿主机上的 PID 信息

image.png

1.1.4.4.2: 查看容器中的 PID 信息

[图片上传失败...(image-994f8-1594221009349)]

1.1.4.5: Net Namespace

每一个容器都类似于虚拟机一样有自己的网卡、 监听端口、 TCP/IP 协议栈等,Docker 使用 network namespace 启动一个 vethX 接口,这样你的容器将拥有它自己的桥接 ip 地址,通常是 docker0,而 docker0 实质就是 Linux 的虚拟网桥,网桥是在 OSI 七层模型的数据链路层的网络设备,通过 mac 地址对网络进行划分,并且在不同网络直接传递数据。

1.1.4.5.1: 查看宿主机的网卡信息

image.png

1.1.4.5.2: 查看宿主机桥接设备

通过 brctl show 命令查看桥接设备

image.png image.png

1.1.4.5.3:实逻辑网络图

image.png

1.1.4.5.4: 宿主机 iptables 规则

image.png image.png

1.1.4.6: User Namespace

各个容器内可能会出现重名的用户和用户组名称, 或重复的用户 UID 或者GID, 那么怎么隔离各个容器内的用户空间呢?User Namespace 允许在各个宿主机的各个容器空间内创建相同的用户名以及相同的用户 UID 和 GID, 只是会把用户的作用范围限制在每个容器内,即 A 容器和 B 容器可以有相同的用户名称和 ID 的账户,但是此用户的有效范围仅是当前容器内, 不能访问另外一个容器内的文件系统,即相互隔离、互补影响、 永不相见。

[图片上传失败...(image-49a06e-1594221009349)]

1.1.5: Linux control groups

1.1.5.1: 验证系统 cgroups:
Cgroups 在内核层默认已经开启, 从 centos 和 ubuntu 对比结果来看, 显然内核
较新的 ubuntu 支持的功能更多。

1.1.5.1.1: Centos 7.6 cgroups

image.png

1.1.5.1.2: ubuntu cgroups

image.png

1.1.5.1.3: cgroups 中内存模块

# cat /boot/config-4.15.0-54-generic | grep MEM | grep CG
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
# CONFIG_MEMCG_SWAP_ENABLED is not set
CONFIG_SLUB_MEMCG_SYSFS_ON=y

1.1.5.1.4: cgroups 具体实现

blkio:块设备 IO 限制。
cpu:使用调度程序为 cgroup 任务提供 cpu 的访问。
cpuacct:产生 cgroup 任务的 cpu 资源报告。
cpuset:如果是多核心的 cpu,这个子系统会为 cgroup 任务分配单独的 cpu
和内存。
devices:允许或拒绝 cgroup 任务对设备的访问。
freezer:暂停和恢复 cgroup 任务。
memory:设置每个 cgroup 的内存限制以及产生内存资源报告。
net_cls:标记每个网络包以供 cgroup 方便使用。
ns:命名空间子系统。
perf_event:增加了对每 group 的监测跟踪的能力,可以监测属于某个特定的
group 的所有线程以及运行在特定 CPU 上的线程。

1.1.5.1.5:查看系统 cgroups

[root@node1 ~]# ll /sys/fs/cgroup/
total 0
drwxr-xr-x 5 root root 0 Jun 30 18:12 blkio
lrwxrwxrwx 1 root root 11 Jun 30 18:12 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Jun 30 18:12 cpuacct -> cpu,cpuacct
drwxr-xr-x 5 root root 0 Jun 30 18:12 cpu,cpuacct
drwxr-xr-x 3 root root 0 Jun 30 18:12 cpuset
drwxr-xr-x 5 root root 0 Jun 30 18:12 devices
drwxr-xr-x 3 root root 0 Jun 30 18:12 freezer
drwxr-xr-x 3 root root 0 Jun 30 18:12 hugetlb
drwxr-xr-x 5 root root 0 Jun 30 18:12 memory
drwxr-xr-x 3 root root 0 Jun 30 18:12 net_cls
drwxr-xr-x 3 root root 0 Jun 30 18:12 perf_event
drwxr-xr-x 5 root root 0 Jun 30 18:12 systemd

有了以上的 chroot、 namespace、 cgroups 就具备了基础的容器运行环境,但是还需要有相应的容器创建与删除的管理工具、 以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题需要解决, 于是容器管理技术出
现了。

1.1.6: 容器管理工具

目前主要是使用 docker, 早期有使用 lxc。

1.1.6.1: lxc:

LXC: LXC 为 Linux Container 的简写。可以提供轻量级的虚拟化,以便隔离进程和资源, 官方网站: https://linuxcontainers.org/

Ubuntu 安装 lxc:

root@s1:~# apt install lxc lxd
Reading package lists... Done
Building dependency tree
Reading state information... Done
lxd is already the newest version (3.0.3-0ubuntu1~18.04.1).
lxc is already the newest version (3.0.3-0ubuntu1~18.04.1).
root@s1:~# lxc-checkconfig #检查内核对 lcx 的支持状况,必须全部为 lcx
root@s1:~# lxc-create -t 模板名称 -n lcx-test
root@s1:~# lxc-create -t download --name alpine12 -- --dist alpine --release
3.9 --arch amd64
Setting up the GPG keyring
Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
You just created an Alpinelinux 3.9 x86_64 (20190630_13:00) container.

root@s1:~# lxc-start alpine12 #启动 lxc 容器
root@s1:~# lxc-attach alpine12 #进入 lxc 容器
~ # ifconfig
eth0 Link encap:Ethernet HWaddr 00:16:3E:DF:54:94
inet addr:10.0.3.115 Bcast:10.0.3.255 Mask:255.255.255.0
inet6 addr: fe80::216:3eff:fedf:5494/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:18 errors:0 dropped:0 overruns:0 frame:0
TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2102 (2.0 KiB) TX bytes:1796 (1.7 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

~ # uname -a
Linux alpine12 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018
x86_64 Linux
~ # cat /etc/issue
Welcome to Alpine Linux 3.9
Kernel \r on an \m (\l)

命令备注:
-t 模板: -t 选项后面跟的是模板,模式可以认为是一个原型,用来说明我们需要一个什么样的容器(比如容器里面需不需要有 vim, apache 等软件).模板实际上就是一个脚本文件(位于/usr/share/lxc/templates 目录),我们这里指定download 模板(lxc-create 会调用 lxc-download 脚本,该脚本位于刚说的模板目录中)是说明我们目前没有自己模板,需要下载官方的模板
--name 容器名称: 为创建的容器命名
-- : --用来说明后面的参数是传递给 download 脚本的,告诉脚本需要下载什么样的模板
--dist 操作系统名称:指定操作系统
--release 操作系统: 指定操作系统,可以是各种 Linux 的变种
--arch 架构: 指定架构,是 x86 还是 arm,是 32 位还是 64 位

lxc 启动容器依赖于模板, 清华模板源:
https://mirrors.tuna.tsinghua.edu.cn/help/lxc-images/,但是做模板相对较难, 需要手动一步步创构建文件系统、准备基础目录及可执行程序等,而且在大规模使用容器的场景很难横向扩展, 另外后期代码升级也需要重新从头构建模板,基于以上种种原因便有了 docker。

1.1.6.2: docker

Docker 启动一个容器也需要一个外部模板但是较多镜像, docke 的镜像可以保存在一个公共的地方共享使用, 只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。
Docker 的镜像是分层的, 镜像底层为库文件且只读层即不能写入也不能删除数据,从镜像加载启动为一个容器后会生成一个可写层,其写入的数据会复制到容器目录, 但是容器内的数据在删除容器后也会被随之删除。

1.1.6.3: pouch

https://www.infoq.cn/article/alibaba-pouch
https://github.com/alibaba/pouch

1.1.7: Docker 的优势

快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上。
高效虚拟化:不需要额外的 hypervisor 支持,直接基于 linux 实现应用虚拟化,相比虚拟机大幅提高性能和效率。
节省开支: 提高服务器利用率,降低 IT 支出。
简化配置: 将运行环境打包保存至容器,使用时直接启动即可。
快速迁移和扩展: 可夸平台运行在物理机、虚拟机、公有云等环境, 良好的兼容性可以方便将应用从 A 宿主机迁移到 B 宿主机, 甚至是 A 平台迁移到 B 平台

1.1.8: Docker 的缺点

隔离性: 各应用之间的隔离不如虚拟机彻底。

小笔记:pouch安装
cd /etc/yum.repos.d
wget https://mirrors.aliyun.com/pouch/centos7.repo
yum install pouch -y
systemctl start pouch
1.1.9: docker(容器)的核心技术

容器规范

容器技术除了的 docker 之外,还有 coreOS 的 rkt, 还有阿里的 Pouch, 为了保证容器生态的标准性和健康可持续发展, 包括 Linux 基金会、 Docker、微软、红帽谷歌和、 IBM、 等公司在 2015 年 6 月共同成立了一个叫 open container(OCI)的组织,其目的就是制定开放的标准的容器规范,目前 OCI 一共发布了两个规范,分别是 runtime spec 和 image format spec,有了这两个规范, 不同的容器公司开发的容器只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性。

容器 runtime:

runtime 是真正运行容器的地方,因此为了运行不同的容器 runtime 需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境。
目前主流的三种 runtime:
Lxc: linux 上早期的 runtime, Docker 早期就是采用 lxc 作为 runtime。
runc:目前 Docker 默认的 runtime, runc 遵守 OCI 规范,因此可以兼容 lxc。
rkt: 是 CoreOS 开发的容器 runtime,也符合 OCI 规范,所以使用 rktruntime 也可以运行 Docker 容器。

容器管理工具:

管理工具连接 runtime 与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给 runtime 执行。
lxc 是 lxd 的管理工具。
Runc 的管理工具是 docker engine, docker engine 包含后台 deamon 和 cli 两部分,大家经常提到的 Docker 就是指的 docker engine。
Rkt 的管理工具是 rkt cli。

容器定义工具:

容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建。
Docker image:是 docker 容器的模板, runtime 依据 docker image 创建容器。
Dockerfile:包含 N 个命令的文本文件,通过 dockerfile 创建出 docker image。
ACI(App container image): 与 docker image 类似, 是 CoreOS 开发的 rkt 容器的镜像格式。

Registry:

统一保存镜像而且是多个不同镜像版本的地方, 叫做镜像仓库。
Image registry: docker 官方提供的私有仓库部署工具。
Docker hub: docker 官方的公共仓库, 已经保存了大量的常用镜像,可以方便大家直接使用。
Harbor: vmware 提供的自带 web 界面自带认证功能的镜像仓库,目前有很多公司使用。

172.18.200.101/project/centos:7.2.1511
172.18.200.101/project/centos: latest
172.18.200.101/project/java-7.0.59:v1
172.18.200.101/project/java-7.0.59:v2

编排工具:

当多个容器在多个主机运行的时候, 单独管理容器是相当复杂而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的, 也无法实现动态伸缩的功能,因此需要有一种工具可以实现统一管理、动
态伸缩、故障自愈、 批量执行等功能, 这就是容器编排引擎。
容器编排通常包括容器管理、调度、集群定义和服务发现等功能。
Docker swarm: docker 开发的容器编排引擎。
Kubernetes: google 领导开发的容器编排引擎,内部项目为 Borg, 且其同时支持docker 和 CoreOS。
Mesos+Marathon: 通用的集群组员调度平台, mesos(资源分配)与 marathon(容器编排平台)一起提供容器编排引擎功能。

1.1.10: docker(容器)的依赖技术

容器网络:
docker 自带的网络 docker network 仅支持管理单机上的容器网络, 当多主机运行的时候需要使用第三方开源网络,例如 calico、 flannel 等。

服务发现:
容器的动态扩容特性决定了容器 IP 也会随之变化, 因此需要有一种机制可以自动识别并将用户请求动态转发到新创建的容器上, kubernetes 自带服务发现功能,需要结合 kube-dns 服务解析内部域名。

容器监控:
可以通过原生命令 docker ps/top/stats 查看容器运行状态,另外也可以使heapster/ Prometheus 等第三方监控工具监控容器的运行状态。

数据管理:

容器的动态迁移会导致其在不同的 Host 之间迁移,因此如何保证与容器相关的数据也能随之迁移或随时访问,可以使用逻辑卷/存储挂载等方式解决。

日志收集:

docker 原生的日志查看工具 docker logs, 但是容器内部的日志需要通过 ELK 等专门的日志收集分析和展示工具进行处理。

1.2: Docker 安装及基础命令介绍

官方网址: https://www.docker.com/
系统版本选择:
Docker 目前已经支持多种操作系统的安装运行, 比如 Ubuntu、 CentOS、Redhat、 Debian、 Fedora,甚至是还支持了 Mac 和 Windows,在 linux 系统上需要内核版本在 3.10 或以上, docker 版本号之前一直是 0.X 版本或 1.X 版本,但是从 2017 年 3 月 1 号开始改为每个季度发布一次稳版,其版本号规则也统一变更为 YY.MM, 例如 17.09 表示是 2017 年 9 月份发布的, 本次演示的操作系统使用 Centos 7.5 为例。

Docker 版本选择:
Docker 之前没有区分版本,但是 2017 年初推出(将 docker 更名为)新的项目Moby, github 地址: https://github.com/moby/moby, Moby 项目属于 Docker 项目的全新上游, Docker 将是一个隶属于的 Moby 的子产品,而且之后的版本之后开始区分为 CE 版本(社区版本) 和 EE(企业收费版), CE 社区版本和 EE 企业版本都是每个季度发布一个新版本,但是 EE 版本提供后期安全维护 1 年, 而CE 版本是 4 个月, 本次演示的 Docker 版本为 18.03, 以下为官方原文:
https://blog.docker.com/2017/03/docker-enterprise-edition/

Docker CE and EE are released quarterly, and CE also has a monthly “Edge” option.
Each Docker EE release is supported and maintained for one year and receives
security and critical bugfixes during that period. We are also improving Docker CE
maintainability by maintaining each quarterly CE release for 4 months. That gets
Docker CE users a new 1-month window to update from one version to the next.

与 kubernetes 结合使用的时候,要安装经过 kubernetes 官方测试通过的 docker
版本, 避免出现不兼容等未知的及不可预估的问题发生, kubernetes 测试过的

docker 版本可以在 github 查询, 具体如下:
https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md#external-dependencies

1.2.1: 下载 rpm 包安装

官方 rpm 包下载地址:
https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
二进制下载地址:
https://download.docker.com/
https://mirrors.aliyun.com/docker-ce/linux/static/stable/x86_64/
阿里镜像下载地址:
https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/

1.2.2: 通过修改 yum 源安装

[root@docker-server1 ~]# rm -rf /etc/yum.repos.d/*
[root@docker-server1 ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo
http://mirrors.aliyun.com/repo/Centos-7.repo
[root@docker-server1 ~]# wget -O /etc/yum.repos.d/epel.repo
http://mirrors.aliyun.com/repo/epel-7.repo
[root@docker-server1 ~]# wget -O /etc/yum.repos.d/docker-ce.repo
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@docker-server1 ~]# yum install docker-ce

1.2:3: ubuntu 安装 docker、 启动并验证服务
root@docker-server1:~#apt-get install docker-ce-5:18.09.9~3-0~ubuntu-bionic
docker-ce-cli=5:18.09.9~3-0~ubuntu-bionic
root@docker-server1:~# systemctl start docker
root@docker-server1:~# systemctl enable docker
小笔记:安装docker
#ubuntu18
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce

# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
apt-cache madison docker-ce
#docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
#docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
sudo apt-get -y install docker-ce=[VERSION]

#centos7
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start

# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
vim /etc/yum.repos.d/docker-ee.repo
#   将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
sudo yum -y install docker-ce-[VERSION]

#简单使用
systemctl start docker
docker pull nginx:1.16.1        #下载nginx镜像
docker run -d -p 80:80 nginx    #运行容器
docker ps                       #查看ID号
docker exec -it id bash         #进入容器
1.2.4: 验证 docker 版本

docker version

1.2.5:验证 docker0 网卡

在 docker 安装启动之后,默认会生成一个名称为 docker0 的网卡并且默认 IP 地址为 172.17.0.1 的网卡。

1.2.6: 验证 docker 信息
root@docker-server1:~# docker info
Containers: 2 #当前主机运行的容器总数
  Running: 1 #有几个容器是正在运行的
  Paused: 0 #有几个容器是暂停的
  Stopped: 1 #有几个容器是停止的
Images: 3 #当前服务器的镜像数
Server Version: 18.09.9 #服务端版本
Storage Driver: overlay2 #正在使用的存储引擎
  Backing Filesystem: xfs #后端文件系统,即服务器的磁盘文件系统
  Supports d_type: true #是否支持 d_type
  Native Overlay Diff: true #是否支持差异数据存储
Logging Driver: json-file #日志类型
Cgroup Driver: cgroupfs #Cgroups 类型
Plugins: #插件
  Volume: local #卷
  Network: bridge host macvlan null overlay # overlay 夸主机通信
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog #日志类型
Swarm: inactive #是否支持 swarm
Runtimes: runc #已安装的容器运行时
Default Runtime: runc #默认使用的容器运行时
Init Binary: docker-init #初始化容器的守护进程,即 pid 为 1 的进程
containerd version: 894b81a4b802e4eb2a91d1ce216b8817763c29fb #版本
runc version: 425e105d5a03fabd737a126ad93d62a9eeede87f # runc 版本
init version: fec3683 #init 版本
  Security Options: #安全选项
  Apparmor #安全模块, https://docs.docker.com/engine/security/apparmor/
  seccomp #审计(操作), https://docs.docker.com/engine/security/seccomp/
Profile: default #默认的配置文件
Kernel Version: 4.15.0-55-generic #宿主机内核版本
Operating System: Ubuntu 18.04.3 LTS #宿主机操作系统
OSType: linux #宿主机操作系统类型
Architecture: x86_64 #宿主机架构
CPUs: 1 #宿主机 CPU 数量
Total Memory: 1.924GiB #宿主机总内存
Name: docker-server1.magedu.net #宿主机 hostname
ID: ZFPD:UIA5:SR6E:Y6SS:52QL:5MPT:VDY3:ATVI:QMVG:HAFF:MN74:2HPD #宿主机ID
Docker Root Dir: /var/lib/docker #宿主机数据保存目录
Debug Mode (client): false #client 端是否开启 debug
Debug Mode (server): false #server 端是否开启 debug
Registry: https://index.docker.io/v1/ #镜像仓库
Labels: #其他标签
Experimental: false #是否测试版
Insecure Registries: #非安全的镜像仓库
  127.0.0.0/8
Live Restore Enabled: false #是否开启活动重启(重启 docker-daemon 不关闭容器)
Product License: Community Engine #产品许可信息
WARNING: No swap limit support #系统警告信息(没有开启 swap 资源限制)
root@docker-server1:~#
1.2.7: 解决不支持 swap 限制警告
root@docker-server1:~# vim /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=2
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 cgroup_enable=memory"
swapaccount=1"
# update-grub
# reboot
1.2.8: docker 存储引擎

目前 docker 的默认存储引擎为 overlay2, 不同的存储引擎需要相应的系统支持,如需要磁盘分区的时候传递 d-type 文件分层功能,即需要传递内核参数开启格式化磁盘的时候的指定功能。

历史更新信息:
https://github.com/moby/moby/blob/master/CHANGELOG.md
官方文档关于存储引擎的选择文档:
https://docs.docker.com/storage/storagedriver/select-storage-driver/

存储驱动类型

AUFS(AnotherUnionFS)是一种 Union FS,是文件级的存储驱动。所谓 UnionFS就是把不同物理位置的目录合并 mount 到同一个目录中。简单来说就是支持将不同目录挂载到同一个虚拟文件系统下的文件系统。这种文件系统可以一层一层地叠加修改文件。无论底下有多少层都是只读的,只有最上层的文件系统是可写的。当需要修改一个文件时, AUFS 创建该文件的一个副本,使用 CoW 将文件从只读层复制到可写层进行修改,结果也保存在可写层。在 Docker 中,底
下的只读层就是 image,可写层就是 Container,是 Docker 18.06 及更早版本的首选存储驱动程序,在内核 3.13 上运行 Ubuntu 14.04 时不支持 overlay2。

Overlay:一种 Union FS 文件系统, Linux 内核 3.18 后支持。

overlay2: Overlay 的升级版,到目前为止,所有 Linux 发行版推荐使用的存储类
型。

devicemapper:是 CentOS 和 RHEL 的推荐存储驱动程序,因为之前的内核版本不支持 overlay2,但是当前较新版本的 CentOS 和 RHEL 现在已经支持 overlay2,因此推荐使用 overlay2。

ZFS(Sun-2005)/btrfs(Oracle-2007):目前没有广泛使用。

vfs:用于测试环境,适用于无法使用 copy-on-write 文件系统的情况。 此存储
驱动程序的性能很差,通常不建议用于生产。

Docker 官方推荐首选存储引擎为 overlay2, devicemapper 存在使用空间方面的一些限制, 虽然可以通过后期配置解决,但是官方依然推荐使用 overlay2,以下是网上查到的部分资料:
https://www.cnblogs.com/youruncloud/p/5736718.html

image.png

如果 docker 数据目录是一块单独的磁盘分区而且是 xfs 格式的, 那么需要在格式化的时候加上参数-n ftype=1, 否则后期在启动容器的时候会报错不支持 dtype。

image.png

Centos 7.2 报错界面

image.png

Centos 7.3 已修复此问题

1.2.9: docker 服务进程

通过查看 docker 进程,了解 docker 的运行及工作方式

1.2.9.1: 查看宿主机进程树

Docker 版本:
Server: Docker Engine - Community
 Engine:
  Version: 18.09.7
  API version: 1.39 (minimum version 1.12)
  Go version: go1.10.8
  Git commit: 2d0083d
  Built: Thu Jun 27 17:26:28 2019
  OS/Arch: linux/amd64
  Experimental: false
image.png

1.2.9.2:查看 containerd 进程关系

有四个进程:
dockerd: 被 client 直接访问,其父进程为宿主机的 systemd 守护进程。
docker-proxy: 实现容器通信, 其父进程为 dockerd
containerd:被 dockerd 进程调用以实现与 runc 交互。
containerd-shim: 真正运行容器的载体, 其父进程为 containerd。

image.png

1.2.9.3: containerd-shim 命令使用

[root@node1 ~]# containerd-shim -h
Usage of containerd-shim:
-address string
grpc address back to main containerd
-containerd-binary containerd publish
path to containerd binary (used for containerd publish) (default "cont
-criu string
path to criu binary
-debug
enable debug output in logs
-namespace string
namespace that owns the shim
-runtime-root string
root directory for the runtime (default "/run/containerd/runc")
-socket string
abstract socket path to serve
-systemd-cgroup
set runtime to use systemd-cgroup
-workdir string
path used to storge large temporary data

1.2.9.4:容器的创建与管理过程

通信流程:
1.dockerd 通过 grpc 和 containerd 模块通信(runc)交换, dockerd 和 containerd通信的 socket 文件: /run/containerd/containerd.sock。
2. containerd 在 dockerd 启动时被启动, 然后 containerd 启动 grpc 请求监听,containerd 处理 grpc 请求,根据请求做相应动作。
/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
3. 若是创建容器, containerd 拉起一个 container-shim 容器进程 , 并进行相应的创建操作。
4. container-shim 被拉起后, start/exec/create 拉起 runC 进程,通过 exit、 control文件和 containerd 通信,通过父子进程关系和 SIGCHLD(信号)监控容器中进程状态。
5. 在整个容器生命周期中, containerd 通过 epoll 监控容器文件,监控容器事件。

1.2.9.5: grpc 简介:
gRPC 是 Google 开发的一款高性能、开源和通用的 RPC 框架,支持众多语言客户端。
https://www.grpc.io/

1.3: docker 镜像加速配置:

国内下载国外的镜像有时候会很慢,因此可以更改 docker 配置文件添加一个加速器, 可以通过加速器达到加速下载镜像的目的。

1.3.1:获取加速地址:

浏览器打开 http://cr.console.aliyun.com, 注册或登录阿里云账号,点击左侧的镜像加速器, 将会得到一个专属的加速地址, 而且下面有使用配置说明:

[图片上传失败...(image-ccd469-1594221009349)]

1.3.2:生成配置文件
[root@docker-server1 ~]# mkdir -p /etc/docker
[root@docker-server1 ~]# sudo tee /etc/docker/daemon.json <<-'EOF'
> {
> "registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"]
> }
> EOF
{
"registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"]
}
[root@docker-server1 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"]
}

1.3.3: 重启 docke 服务

[root@docker-server1 ~]# systemctl daemon-reload
[root@docker-server1 ~]# sudo systemctl restart docker

1.4: Docker 镜像管理

Docker 镜像含有启动容器所需要的文件系统及所需要的内容, 因此镜像主要用于创建并启动 docker 容器。

Docker 镜像含里面是一层层文件系统,叫做 Union File System(Union FS 联合文件系统), 2004 年由纽约州立大学石溪分校开发,联合文件系统可以将多个目录挂载到一起从而形成一整个虚拟文件系统,该虚拟文件系统的目录结构就像普通 linux 的目录结构一样, docker 通过这些文件再加上宿主机的内核提供了一个 linux 的虚拟环境,每一层文件系统我们叫做一层 layer,联合文件系统可以对每一层文件系统设置三种权限,只读(readonly)、读写(readwrite)和写出whiteout-able),但是 docker 镜像中每一层文件系统都是只读的,构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样,当使用镜像的时候,我们只会看到一个完全的整体,不知道里面有几层也不需要知道里面有几层,结构如下:

image.png
# pwd
/usr/local/src
#mkdir a b system
#touch a/a.txt b/b.txt
#mount -t aufs -o dirs=./a:./b none ./system/
#tree system/
system/
├── a.txt
└── b.txt

0 directories, 2 file

一个典型的 Linux 文件系统由 bootfs 和 rootfs 两部分组成, bootfs(boot filesystem) 主要包含 bootloader 和 kernel, bootloader 主要用于引导加载 kernel,当 kernel 被加载到内存中后 bootfs 会被 umount 掉, rootfs (root file system) 包
含的就是典型 Linux 系统中的/dev, /proc, /bin, /etc 等标准目录和文件, 下图就是 docker image 中最基础的两层结构,不同的 linux 发行版(如 ubuntu和 CentOS ) 在 rootfs 这一层会有所区别。

但是对于 docker 镜像通常都比较小, 官方提供的 centos 基础镜像在 200MB 左右,一些其他版本的镜像甚至只有几 MB, docker 镜像直接调用宿主机的内核,镜像中只提供 rootfs,也就是只需要包括最基本的命令、工具和程序库就可以
了, 比如 alpine 镜像,在 5M 左右。

下图就是有两个不同的镜像在一个宿主机内核上实现不同的 rootfs。

image.png

容器、 镜像父镜像:

image.png
小笔记
#导出镜像
docker save centos > /opt/centos.tar.gz

docker 命令是最常使用的 docker 客户端命令,其后面可以加不同的参数以实现响应的功能,常用的命令如下:

1.4.1: 搜索镜像:

在官方的 docker 仓库中搜索指定名称的 docker 镜像, 也会有很多镜像。

[root@docker-server1 ~]# docker search centos:7.2.1511 #带指定版本号
[root@docker-server1 ~]# docker search centos #不带版本号默认 latest
1.4.2: 下载镜像

从 docker 仓库将镜像下载到本地, 命令格式如下:

# docker pull 仓库服务器:端口/项目名称/镜像名称:tag(版本)号
[root@docker-server1 ~]# docker pull alpine
[root@docker-server1 ~]# docker pull nginx
[root@docker-server1 ~]# docker pull hello-world
[root@docker-server1 ~]# docker pull centos
小笔记
#查看镜像历史
docker history centos
1.4.3: 查看本地镜像:

#下载完成的镜像比下载的大,因为下载完成后会解压

[root@docker-server1 ~]# docker images  

REPOSITORY #镜像所属的仓库名称
TAG #镜像版本号(标识符), 默认为 latest
IMAGE ID #镜像唯一 ID 标示
CREATED #镜像创建时间
VIRTUAL SIZE #镜像的大小
1.4.4: 镜像导出

可以将镜像从本地导出为一个压缩文件,然后复制到其他服务器进行导入使用。

#导出方法 1:  
[root@docker-server1 ~]# docker save centos -o /opt/centos.tar.gz
[root@docker-server1 ~]# ll /opt/centos.tar.gz
-rw------- 1 root root 205225472 Nov 1 03:52 /opt/centos.tar.gz
#导出方法 2:
[root@docker-server1 ~]# docker save centos > /opt/centos-1.tar.gz
[root@docker-server1 ~]# ll /opt/centos-1.tar.gz
-rw-r--r-- 1 root root 205225472 Nov 1 03:52 /opt/centos-1.tar.gz
#查看镜像内容:  
[root@docker-server1 ~]# cd /opt/
[root@docker-server1 opt]# tar xvf centos.tar.gz
[root@docker-server1 opt]# cat manifest.json #包含了镜像的相关配置, 配置文件、分层
[{"Config":"196e0ce0c9fbb31da595b893dd39bc9fd4aa78a474bbdc21459a3ebe855b
7768.json","RepoTags":["docker.io/centos:latest"],"Layers":["892ebb5d1299cbf459f6
7aa070f29fdc6d83f4025c58c090e9a69bd4f7af436b/layer.tar"]}]
#分层为了方便文件的共用,即相同的文件可以共用  
[{"Config":" 配 置 文 件 .json","RepoTags":["docker.io/nginx:latest"],"Layers":[" 分 层
1/layer.tar","分层 2 /layer.tar","分层 3 /layer.tar"]}]
1.4.5: 镜像导入
#将镜像导入到 docker
[root@docker-server1 ~]# scp /opt/centos.tar.gz 192.168.10.206:/opt/
[root@docker-server2 ~]# docker load < /opt/centos.tar.gz

验证镜像

docker images
1.4.6:删除镜像
[root@docker-server1 opt]# docker rmi centos

#获取运行参数帮助

[root@linux-docker opt]# docker daemon --help  

总结: 企业使用镜像及常见操作:
搜索、 下载、导出、导入、删除

命令总结:
# docker load -i centos-latest.tar.xz #导入本地镜像
# docker save > /opt/centos.tar #centos #导出镜像
# docker rmi 镜像 ID/镜像名称 #删除指定 ID 的镜像,通过镜像启动容器的时
候镜像不能被删除,除非将容器全部关闭
# docker rm 容器 ID/容器名称 #删除容器
# docker rm 容器 ID/容器名-f #强制删除正在运行的容器

1.5: 容器操作基础命令

命令格式

docker run [选项] [镜像名] [shell 命令] [参数]
docker run [参数选项] [镜像名称,必须在所有选项的后面] [/bin/echo 'hellowold'] #单次执行,没有自定义容器名称
docker run centos /bin/echo 'hello wold' #启动的容器在执行完 shel 命令就退出了
1.5.1:从镜像启动一个容器

会直接进入到容器, 并随机生成容器 ID 和名称

[root@docker-server1 ~]# docker run -it docker.io/centos bash
[root@11445b3a84d3 /]#  

#退出容器不注销
ctrl+p+q

1.5.2: 显示正在运行的容器
[root@linux-docker ~]# docker ps  
1.5.3: 显示所有容器:

包括当前正在运行以及已经关闭的所有容器:

[root@linux-docker ~]# docker ps -a  
1.5.4: 删除运行中的容器:

即使容正在运行当中, 也会被强制删除掉

[root@docker-server1 ~]# docker rm -f 11445b3a84d3  
1.5.5: 随机映射端口
[root@docker-server1 ~]# docker pull nginx #下载 nginx 镜像
[root@docker-server1 ~]# docker run -P docker.io/nginx #前台启动并随机映射本地端口到容器的 80  

前台启动的会话窗口无法进行其他操作,除非退出, 但是退出后容器也会退出

随机端口映射, 其实是默认从 32768 开始

1.5.6: 指定端口映射
方式 1:本地端口 81 映射到容器 80 端口:
# docker run -p 81:80 --name nginx-test-port1 nginx
方式 2:本地 IP:本地端口:容器端口
# docker run -p 192.168.10.205:82:80 --name nginx-test-port2 docker.io/nginx
方式 3:本地 IP:本地随机端口:容器端口
# docker run -p 192.168.10.205::80 --name nginx-test-port3 docker.io/nginx
方式 4:本机 ip:本地端口:容器端口/协议,默认为 tcp 协议
# docker run -p 192.168.10.205:83:80/udp --name nginx-test-port4
docker.io/nginx
方式 5:一次性映射多个端口+协议:
# docker run -p 86:80/tcp -p 443:443/tcp -p 53:53/udp --name nginx-test-port5
docker.io/nginx
1.5.7: 查看容器已经映射的端口
[root@docker-server1 ~]# docker port nginx-test-port5  
1.5.8: 自定义容器名称
[root@docker-server1 ~]# docker run -it --name nginx-test nginx  
1.5.9: 后台启动容器
[root@docker-server1 ~]# docker run -d -P --name nginx-test1 docker.io/nginx
9aaad776850bc06f516a770d42698e3b8f4ccce30d4b142f102ed3cb34399b31  
1.5.10:创建并进入容器:
[root@docker-server1 ~]# docker run -t -i --name test-centos2 docker.io/centos
/bin/bash
[root@a8fb69e71c73 /]# #创建容器后直接进入, 执行 exit 退出后容器关闭  

[root@docker-server1 ~]# docker run -d --name centos-test1 docker.io/centos
2cbbec43ba939476d798a5e1c454dd62d4d893ee12a09b587556ba6395353152  
1.5.11:单次运行
#容器退出后自动删除:
[root@linux-docker opt]# docker run -it --rm --name nginx-delete-test
docker.io/nginx
1.5.12: 传递运行命令

容器需要有一个前台运行的进程才能保持容器的运行, 通过传递运行参数是一种方式, 另外也可以在构建镜像的时候指定容器启动时运行的前台命令。

[root@docker-server1 ~]# docker run -d centos /usr/bin/tail -f '/etc/hosts'
1.5.13:容器的启动和关闭
[root@docker-server1 ~]# docker stop f821d0cd5a99
[root@docker-server1 ~]# docker start f821d0cd5a99

1.5.14: 进入到正在运行的容器

1.5.14.1:使用 attach 命令

使用方式为 docker attach 容器名, attach 类似于 vnc, 操作会在各个容器界面显示, 所有使用此方式进入容器的操作都是同步显示的且 exit 后容器将被关闭, 且使用 exit 退出后容器关闭,不推荐使用, 需要进入到有 shell 环境的容器,比如 centos 为例:

[root@s1 ~]# docker run -it centos bash
[root@63fbc2d5a3ec /]#
[root@s1 ~]# docker attach 63fbc2d5a3ec
[root@63fbc2d5a3ec /]#

在另外一个窗口启动测试页面是否同步

1.5.14.2:使用 exec 命令

执行单次命令与进入容器,不是很推荐此方式, 虽然 exit 退出容器还在运行

1.5.14.3: 使用 nsenter 命令

推荐使用此方式, nsenter 命令需要通过 PID 进入到容器内部,不过可以使用 docker inspect 获取到容器的 PID:

[root@docker-server1 ~]# yum install util-linux #安装 nsenter 命令
[root@docker-server1 ~]# docker inspect -f "{{.NetworkSettings.IPAddress}}" 91fc190cb538
172.17.0.2
[root@docker-server1 ~]# docker inspect -f "{{.State.Pid}}" mydocker #获取到某个docker 容器的 PID,可以通过 PID 进入到容器内
[root@docker-server1 ~]# docker inspect -f "{{.State.Pid}}" centos-test3
5892
[root@docker-server1 ~]# nsenter -t 5892 -m -u -i -n -p     
-m  挂载namespace
-u  uts
-i  ipc
-n  network
-p  pid
[root@66f511bb15af /]# ls

1.5.14.4: 脚本方式

将 nsenter 命令写入到脚本进行调用,如下:

[root@docker-server1 ~]# cat docker-in.sh
#!/bin/bash
    docker_in(){
    NAME_ID=$1
    PID=$(docker inspect -f "{{.State.Pid}}" ${NAME_ID})
    nsenter -t ${PID} -m -u -i -n -p
}
docker_in $1

#测试脚本是否可以正常进入到容器且退出后仍然正常运行:
[root@docker-server1 ~]# chmod a+x docker-in.sh
[root@docker-server1 ~]# ./docker-in.sh centos-test3
[root@66f511bb15af /]# pwd
/
[root@66f511bb15af /]# exit
logout
[root@docker-server1 ~]# ./docker-in.sh centos-test3
[root@66f511bb15af /]# exit
Logout

1.5.15: 查看容器内部的 hosts 文件

[root@docker-server1 ~]# docker run -i -t --name test-centos3 docker.io/centos
/bin/bash
[root@056bb4928b64 /]# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.4 056bb4928b64 #默认会将实例的 ID 添加到自己的 hosts 文件

1.5.16: 批量关闭正在运行的容器

[root@docker-server1 ~]# docker stop $(docker ps -a -q) #正常关闭所有运行中的容器

1.5.17: 批量强制关闭正在运行的容器

[root@docker-server1 ~]# docker kill $(docker ps -a -q) #强制关闭所有运行中的容器

1.5.18: 批量删除已退出容器

[root@docker-server1 ~]# docker rm -f `docker ps -aq -f status=exited`

1.5.19:批量删除所有容器

[root@docker-server1 ~]# docker rm -f $(docker ps -a -q)

1.5.20: 指定容器 DNS

Dns 服务,默认采用宿主机的 dns 地址
一是将 dns 地址配置在宿主机
二是将参数配置在 docker 启动脚本里面 –dns=1.1.1.1

[root@docker-server1 ~]# docker run -it --rm --dns 223.6.6.6 centos bash
[root@afeb628bf074 /]# cat /etc/resolv.conf
nameserver 223.6.6.6

上一篇下一篇

猜你喜欢

热点阅读