1.梳理各 Namespace 的作用
(1)MNT Namespace
提供磁盘挂载点和文件系统的隔离:
每个容器都要有独立的根文件系统有独立的用户空间,以实现在容器里面启动服务并且使用容器的运行环境,即一个宿主机是 ubuntu 的服务器,可以在里面启动一个 centos 运行环境的容器并且在容器里面启动
一个 Nginx 服务,此 Nginx 运行时使用的运行环境就是 centos 系统目录的运行环境,即在容器里面是不能直接访问宿主机的文件系统。
宿主机是使用了 chroot 技术把容器锁定到一个指定的运行目录里面并作为容器的根运行环境。
(2)IPC Namespace
提供进程间通信的隔离:
IPC namespce 隔离进程间通信资源(同一个 IPC namespace 的进程可实现内 存等资源共享,但是不同的 IPC namespace 则严格隔离)主进程。
(3)UTS Namespace
提供主机名隔离:
UTS namespace(UNIX Timesharing System 包含了运行内核的名称、版本、底层体系结 构类型等信息)用于系统标识, 其中包含了 hostname 和域名 domainname,它使得一个容 器拥有属于自己 hostname 标 识,这个主机名标识独立于宿主 机系统和其上的其他容器。
(4)PID Namespace
提供进程隔离:
Linux 系统中,有一个 PID 为 1 的进 程(init/systemd)是其他所有进程 的父进程,那么在每个容器内也 要有一个父进程来管理其下属的 子进程,那么多个容器的进程通 PID namespace 进程隔离(比如 PID 编号重复、器内的主进程生成 与回收子进程等)。
(5)Net Namespace
提供网络隔离:
每一个容器都类似于虚拟机一 样有自己的网卡、监听端口、TCP/IP 协议栈等,docker 使用 network namespace 启动一 个 vethX 接口,这样你的容器 将拥有它自己的桥接 ip 地址, 通常是 docker0,docker0 实质就是 Linux 的虚拟网桥,网 桥是在 OSI 七层模型的数据链 路层的网络设备,通过 mac 地 址对网络进行划分,并且在不 同网络直接传递数据。
(6)User Namespace
提供用户隔离:
各个容器内可能会出现重名的用户 和用户组名称,或重复的用户 UID 或者 GID,那么怎么隔离各个容器 内的用户空间呢? üUser Namespace 允许在各个宿 主机的各个容器空间内创建相同的 用户名以及相同的用户 UID 和 GID,只是会把用户的作用范围限 制在每个容器内,即 A 容器和 B 容 器可以有相同的用户名称和 ID 的账 户,但是此用户的有效范围仅是当 前容器内,不能访问另外一个容器 内的文件系统,即相互隔离、互不影响.
(7)Control group (cgroup) Namespace
在一个容器,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码 bug 程序会一直申请内存,直到把宿主机内存 占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如 CPU、内存等,Linux Cgroups 的全称是 Linux Control Groups,它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,以及将进程挂 起和恢复等操作。
2.使用 apt 安装指定版本的 Docker
(1)卸载旧版本 docker
#Uninstall old versions
chen@chen:~$ sudo apt-get remove docker docker-engine docker.io containerd runc
复制代码
(2)设置 apt 源
#Update the apt package index and install packages to allow apt to use a repository over HTTPS
chen@chen:~$ sudo apt-get update
chen@chen:~$ sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
#Add Docker’s official GPG key
chen@chen:~$ sudo mkdir -p /etc/apt/keyrings
chen@chen:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
#Use the following command to set up the repository
chen@chen:~$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
复制代码
(3)安装 Docker
#Update the apt package index
chen@chen:~$ sudo apt-get update
chen@chen:~$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
chen@chen:~$ sudo apt-get update
# List the available versions
chen@chen:~$ apt-cache madison docker-ce | awk '{ print $3 }'
5:20.10.20~3-0~ubuntu-focal
5:20.10.19~3-0~ubuntu-focal
5:20.10.18~3-0~ubuntu-focal
.......
#Select the desired version and install
chen@chen:~$ VERSION_STRING=5:20.10.20~3-0~ubuntu-focal
chen@chen:~$ sudo apt-get install docker-ce=$VERSION_STRING docker-ce-cli=$VERSION_STRING containerd.io docker-compose-plugin
#Start docker service
chen@chen:~$ sudo systemctl start docker
chen@chen:~$ sudo systemctl enable docker
chen@chen:~$ sudo systemctl status docker
#Verify that the Docker Engine installation is successful
chen@chen:~$ sudo docker info
复制代码
3.熟练使用 Docker 数据卷
数据卷实际上就是宿主机上的目录或者是文件,可以被直接 mount 到容器当中作为容器的本地文件系统使用,当容器中产生的新数据即可保存到宿主机以实现数据持久化的目的。
#Create volume
chen@chen:~$ sudo docker volume create local-vol1
#List volume
chen@chen:~$ sudo docker volume ls
DRIVER VOLUME NAME
local local-vol1
#Inspect volume
chen@chen:~$ sudo docker inspect local-vol1
[
{
"CreatedAt": "2022-10-23T13:43:03Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/local-vol1/_data",
"Name": "local-vol1",
"Options": {},
"Scope": "local"
}
]
#Mount volume
chen@chen:~$ sudo docker run -d -it --name nginx -p 80:80 -v local-vol1:/usr/share/nginx/html nginx
#curl index
chen@chen:~$ curl http://192.168.6.90
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
..............
#Write to volume
chen@chen:~$ sudo docker exec -ti nginx bash
chen@chen:~$ echo "nginx web" > /usr/share/nginx/html/index.html
chen@chen:~$ exit
#Curl index from VM
chen@chen:~$ curl 192.168.6.90:80
nginx web
#Remove nginx container
chen@chen:~$ docker stop nginx
chen@chen:~$ sudo docker rm nginx
chen@chen:~$ sudo cat /var/lib/docker/volumes/local-vol1/_data/index.html
nginx web
#Remove volume
chen@chen:~$ sudo docker volume rm local-vol1
local-vol1
chen@chen:~$ sudo cat /var/lib/docker/volumes/local-vol1/_data/index.html
cat: /var/lib/docker/volumes/local-vol1/_data/index.html: No such file or directory
复制代码
4.熟练使用 Docker 的 bridge 和 container 模式网络
(1)Docker 中的网络模式
Docker 网络-bridge 模式:
docker 的默认模式即不指定任何模式就是 bridge 模式,也是目前使用比较多的网络模式,此模式创建的容器会为每一个容器分配自己的网络 IP 等信息,并将容器连接到一个虚拟网桥与外界通信。
chen@chen:~$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
bcd87ff9b194 bridge bridge local
118b2dde0eb6 host host local
c4f49f0dedc9 none null local
chen@chen:~$ sudo docker network create brg-net1
dcec56cb22c2e97ccc5a89095280f6fd0a0662cb6461db7234fabb8f9e78c25e
chen@chen:~$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
dcec56cb22c2 brg-net1 bridge local
bcd87ff9b194 bridge bridge local
118b2dde0eb6 host host local
c4f49f0dedc9 none null local
chen@chen:~$ sudo docker run -d -it --name nginx --network brg-net1 -p 8090:80 nginx
97430382d140bb8a08ef758d6d3035bdc219872dbcfa0f29131164265a4e86bc
chen@chen:~$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
dcec56cb22c2 brg-net1 bridge local
bcd87ff9b194 bridge bridge local
118b2dde0eb6 host host local
c4f49f0dedc9 none null local
chen@chen:~$ sudo curl http://192.168.6.90:8090
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
.........
复制代码
Docker 网络-container 模式:
Container 模式即容器模式,使用参数--net=container:目标容器名称/ID 指定,使用此模式创建的容器需指定和一个已经存在的容器共享一个网络 namespace,而不会创建独立的 namespace,即新创建的容器不会创建自己的网卡也不会配置自己的 IP,而是和一个已经存在的被指定的 目标容器共享对方的 IP 和端口范围,因此这个容器的端口不能和被指定的目标容器端口冲突,除了网络之外的文件系统、用户信息、进程信息 等仍然保持相互隔离,两个容器的进程可以通过 lo 网卡及容器 IP 进行通信。
#Run nginx-container
chen@chen:~$ sudo docker run -it -d --name nginx-container -p 80:80 --net=bridge nginx:1.22.0-alpine
1252f2804e02f3c642238163018c72f0631c459e2e51a689adecf4e27d5f2863
#Run php-container
chen@chen:~$ sudo docker run -it -d --name php-container --net=container:nginx-container php:7.4.30-fpm-alpine
5416e90b73463d182a094f1df39ac654190f900cffa2cf62c0718ea26976d02c
#Check nginx-container network
chen@chen:~$ sudo docker exec -ti nginx-container sh
/ #
/ #
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # exit
#Check php-container network
chen@chen:~$ sudo docker exec -ti php-container sh
/var/www/html #
/var/www/html #
/var/www/html # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
复制代码
评论