企业级容器技术Docker 20250919总结

接上:企业级容器技术Docker 20250917总结-CSDN博客

八、Docker网络管理

1.Docker的默认的网络通信(学习)

Docker 服务安装完成之后,默认在每个宿主机会生成一个名称为 docker0 的网卡其 IP 地址都是
172.17.0.1/16
[root@ubuntu1804 ~] #apt -y install bridge-utils
[root@ubuntu1804 ~] #brctl show

2.创建容器后的网络配置

veth Virtual Ethernet )是 Linux 内核中的一种虚拟网络设备,通常用于连接两个网络命名空间。 veth 设备总是成对出现,当在一个网络命名空间中创建veth 设备时,会同时创建两个端点。 veth 设备的两个端点可以被看作是一个虚拟的以太网电缆,任何发送到其中一个端点的数据包都会被立即从另一个端点传出。

3.容器间的通信

默认情况下
同一个宿主机的不同容器可相互通信, 不同宿主机之间的容器IP地址重复,默认不能相互通信
dockerd   --icc   Enable inter-container communication (default true )
--icc = false   # 此配置可以禁止同一个宿主机的容器之间通信
范例 : 同一个宿主机不同容器间禁止通信
[root@ubuntu1804 ~] #vim /lib/systemd/system/docker.service
ExecStart = /usr/bin/dockerd -H fd:// --containerd = /run/containerd/containerd.sock
--icc = false
[root@ubuntu1804 ~] #systemctl daemon-reload
[root@ubuntu1804 ~] #systemctl restart docker
# 创建两个容器 , 测试无法通信
[root@ubuntu1804 ~] #docker run -it --name test1 --rm alpine sh
/ # hostname -i
172 .17.0.2
[root@ubuntu1804 ~] #docker run -it --name test2 --rm alpine sh
/ # hostname -i
172 .17.0.3
/ # ping 172.17.0.2
# 添加 --icc 选项,本质上就是修改 iptables 规则 -A FORWARD -i docker0 -o docker0 -j
ACCEPT 修改为 DROP
[root@ubuntu2204 ~] #iptables -S > icc.txt
[root@ubuntu2204 ~] #diff icc.txt no_icc.txt
13c13
< -A FORWARD -i docker0 -o docker0 -j DROP
---
> -A FORWARD -i docker0 -o docker0 -j ACCEPT

4.修改默认docker0网桥的网络配置

范例: docker0IP修改为指定IP
#方法1   daemon.json 配置修改
[root@ubuntu1804 ~]#vim /etc/docker/daemon.json 
[root@ubuntu1804 ~]#cat /etc/docker/daemon.json
{
   "bip": "192.168.100.1/24",
  "registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"] }
[root@ubuntu1804 ~]#systemctl restart docker.service

#方法2  docker.service 配置修改
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 
--bip=192.168.100.1/24 
[root@ubuntu1804 ~]#systemctl daemon-reload 
[root@ubuntu1804 ~]#systemctl restart docker.service
# 注意两种方法不可混用 , 否则将无法启动 docker 服务

5.修改默认网络设置使用自定义网桥

[root@ubuntu1804 ~] #apt -y install bridge-utils
[root@ubuntu1804 ~] #brctl addbr br0
# 给网桥添加 IP ,用于给容器分配置 IP ,如果不指定 IP ,会自动向后续网段,默认是 172.18.0.0/16
[root@ubuntu1804 ~] #ip a a 192.168.100.1/24 dev br0
[root@ubuntu1804 ~] #vim /lib/systemd/system/docker.service
ExecStart = /usr/bin/dockerd -H fd:// --containerd = /run/containerd/containerd.sock -b br0
[root@ubuntu1804 ~] #systemctl daemon-reload
[root@ubuntu1804 ~] #systemctl restart docker

九、容器名称互联(了解)

docker run 创建容器,可使用 --link 选项实现容器名称的引用,其本质就是在容器内的 /etc/hosts 中添加 --link后指定的容器的 IP 和主机名的对应关系,从而实现名称解析
--link list                           #Add link to another container
格式 :  
docker run --name < 容器名称 > # 先创建指定名称的容器
docker run --link < 目标通信的容器 ID 或容器名称 >     # 再创建容器时引用上面容器的名称

实战案例1: 使用容器名称进行容器间通信

[root@ubuntu1804 ~] #docker run -it --name server1 --rm alpine:3.11 sh
/ # cat /etc/hosts
172 .17.0.2 cdb5173003f5   #假设有此ip name
/ # ping cdb5173003f5   #结果显示可以ping通
新建第二个容器时引用第一个容器的名称
会自动将第一个主机的名称加入 /etc/hosts 文件 , 从而可以利用第一个容器名称进行访问
[root@ubuntu1804 ~] #docker run -it --rm --name server2 --link server1 alpine:3.11 sh
/ # env
/ # cat /etc/hosts
172 .17.0.2 server1 cdb5173003f5
172 .17.0.3 7ca466320980
/ # ping server1    可以ping通

实战案例2: 实现 wordpress MySQL 两个容器互连

docker run -d --name mysql -e MYSQL_ROOT_PASSWORD = 123456 -e
MYSQL_DATABASE = wordpress -e MYSQL_USER = wordpress -e MYSQL_PASSWORD = 123456
registry.cn-beijing.aliyuncs.com/xiaoming/mysql:8.0.29-oracle
# 方式 1
docker run -p 80 :80 --name wordpress --link mysql -d registry.cn-beijing.aliyuncs.com/xiaoming/wordpress:php8.2-apache
# 方式 2
docker run -p 80 :80 --name wordpress --link mysql   -e WORDPRESS_DB_HOST = mysql -e
WORDPRESS_DB_NAME = wordpress -e WORDPRESS_DB_USER = wordpress -e
WORDPRESS_DB_PASSWORD = 123456   -d registry.cn-
beijing.aliyuncs.com/xiaoming/wordpress:php8.2-apache
[root@centos7 ~] #tree lamp_docker/
lamp_docker/
├── env_mysql.list
├── env_wordpress.list
└── mysql
  └── mysql_test.cnf
1 directory, 3 files
[root@centos7 ~] #cat lamp_docker/env_mysql.list
MYSQL_ROOT_PASSWORD = 123456
MYSQL_DATABASE = wordpress
MYSQL_USER = wpuser
MYSQL_PASSWORD = wppass
[root@centos7 ~] #cat lamp_docker/env_wordpress.list
WORDPRESS_DB_HOST = mysql:3306
WORDPRESS_DB_NAME = wordpress
WORDPRESS_DB_USER = wpuser
WORDPRESS_DB_PASSWORD = wppass
WORDPRESS_TABLE_PREFIX = wp_
[root@centos7 ~] #cat lamp_docker/mysql/mysql_test.cnf
[mysqld]
server-id = 100
log-bin = mysql-bin
[root@centos7 ~] #docker run --name mysql -v /root/lamp_docker/mysql/:/etc/mysql/conf.d -v /data/mysql:/var/lib/mysql --env-file=/root/lamp_docker/env_mysql.list -d -p 3306:3306 registry.cn-beijing.aliyuncs.com/xiaoming/mysql:8.0.29-oracle
[root@centos7 ~] #docker run -d   --name wordpress --link mysql -v
/data/wordpress:/var/www/html/wp-content --env-file=/root/lamp_docker/env_wordpress.list -p 80:80 registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache

十、Docker 网络连接模式(重点)

Docker 的网络支持 5 种网络模式 :
none,host,bridge,cotainer,network-name
范例:查看默认的网络模式有三个
[root@ubuntu1804 ~] #docker network ls
NETWORK ID         NAME           DRIVER         SCOPE
fe08e6d23c4c         bridge             bridge             local
cb64aa83626c        host                host                local
10619d45dcd4        none               null                 local
网络模式指定
默认新建的容器使用 Bridge 模式,创建容器时, docker run 命令使用以下选项指定网络模式
docker run --network <mode>
docker run --net = <mode>
<mode>: 可是以下值
none
bridge
host
container:< 容器名或容器 ID>
< 自定义网络名称 >

1.Bridge网络模式(默认模式)

[root@ubuntu1804 ~] #docker network inspect bridge    #查看bridge模式信息

[root@ubuntu1804 ~]#cat /proc/sys/net/ipv4/ip_forward   #安装docker.默认启用ip_forward 为1
[root@ubuntu1804 ~]#iptables -vnL -t nat    #宿主机的网络状态

范例: 通过宿主机的物理网卡利用SNAT访问外部网络

[root@centos7 ~] #apt install httpd -y # 在另一台主机上建立 httpd 服务器
[root@ubuntu1804 ~] #docker run -it --rm alpine:3.11 sh   # 启动容器,默认是 bridge网络模式
/ # wget -qO - 10.0.0.7
Website on 10 .0.0.7

2.修改默认的 Bridge 模式网络配置

范例: 修改Bridge模式默认的网段方法1
# 修改桥接地址
[root@ubuntu1804 ~] #vim /lib/systemd/system/docker.service
ExecStart = /usr/bin/dockerd -H fd:// --containerd = /run/containerd/containerd.sock --bip = 10 .100.0.1/24
[root@ubuntu1804 ~] #systemctl daemon-reload
[root@ubuntu1804 ~] #systemctl restart docker
[root@ubuntu1804 ~] #docker run -it --rm alpine sh
/ # ip a
......
inet 10 .100.0.2/24 brd 10 .100.0.255 scope global eth0

.....

范例: 修改Bridge网络配置方法2

[root@ubuntu1804 ~] #vim /etc/docker/daemon.json
{
  "hosts": ["tcp://0.0.0.0:2375", "fd://"],
  "bip": "192.168.100.100/24",         // 分配docker0网卡的IP,24是容器IP的netmask
  "fixed-cidr": "192.168.100.128/26",  // 分配容器IP范围,26不是容器IP的子网掩码,只表示地址范围
  "fixed-cidr-v6": "2001:db8::/64",
  "mtu": 1500,
  "default-gateway": "192.168.100.200",// 网关必须和bip在同一个网段
  "default-gateway-v6": "2001:db8:abcd::89",
  "dns": ["1.1.1.1", "8.8.8.8"]
}
[root@ubuntu1804 ~] #systemctl restart docker
[root@ubuntu1804 ~] #docker run -it --name b1 busybox
/ # ip a        #可以看到更改了网段
/ # cat /etc/resolv.conf
nameserver 1 .1.1.1
nameserver 8 .8.8.8
/ # route -n

3.Host 模式

Host 网络模式特点 :
·使用参数 --network host 指定
·共享宿主机网络,主机名称
·各容器网络无隔离
·网络性能无损耗
·网络故障排除相对简单
·容易产生端口冲突
·网络资源无法分别统计
·不支持端口映射

范例:

[root@ubuntu1804 ~] #ifconfig     #查看宿主机的网络设置
[root@ubuntu1804 ~] #route -n
[root@ubuntu1804 ~] #ss -ntl|grep :80  # 打开容器前确认宿主机的 80/tcp 端口没有打开
[root@ubuntu1804 ~] #docker run -d --network host --name ns nginx:1.6.1 # 创建 host 模式的容器
[root@ubuntu1804 ~] #ss -ntlp|grep :80   # 创建容器后,宿主机的 80/tcp 端口打开
无法实现端口映射
[root@ubuntu1804 ~] #docker run -d --network host --name web2 -p 81:80 nginx-centos7-base:1.6.1
WARNING: Published ports are discarded when using host network mode
6b6a910d79d94b188f719bc6ad00c274acd76a4a2929212157cd49b5219d44ae

4.None 模式

在使用 none 模式后, Docker 容器不会进行任何网络配置,没有网卡、没有 IP 也没有路由,因此默认无
法与外界通信,需要手动添加网卡配置 IP 等,所以极少使用
none 模式特点
·使用参数 --network none 指定
·默认无网络功能,无法和外部通信
·无法实现端口映射
·适用于测试环境
范例: 启动 none 模式的容器
[root@ubuntu1804 ~] #docker run -d --network none -p 8001:80 --name web1-none
nginx-centos7-base:1.6.1     进入容器执行下面的命令,无法ping通网络

5.Container 模式

使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP ,而是和一个被指定的已经存在的容器共享 IP 和端口范围,因此这个容器的端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信。
Container 模式特点
·使用参数 –-network container: 名称或 ID 指定。
·与宿主机网络空间隔离。
·空器间共享网络空间, 直接使用对方的网络。
·第一个容器的网络可能是bridge ,或 none ,或者 host ,而第二个容器模式依赖于第一个容器,它
们共享网络。
·如果第一个容器停止,将导致无法创建第二个容器。
·第二个容器可以直接使用127.0.0.1 访问第一个容器。
·适合频繁的容器间的网络通信。
·默认不支持端口映射,较少使用。

范例: 通过容器模式实现 wordpress

方法 1:WordPress 作为网络基础,MySQL 共享其网络

# 启动WordPress容器,暴露80端口并挂载数据卷
[root@ubuntu2004 ~]# docker run -d \
  -p 80:80 \
  --name wordpress \
  -v /data/wordpress:/var/www/html \
  --restart=always \
  registry.cn-beijing.aliyuncs.com/xiaoming/wordpress:php8.2-apache

# 启动MySQL容器,共享WordPress的网络命名空间(无需单独暴露端口)
[root@ubuntu2004 ~]# docker run \
  --network container:wordpress \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -e MYSQL_DATABASE=wordpress \
  -e MYSQL_USER=wordpress \
  -e MYSQL_PASSWORD=123456 \
  --name mysql \
  -d \
  -v /data/mysql:/var/lib/mysql \
  --restart=always \
  registry.cn-beijing.aliyuncs.com/xiaoming/mysql:8.0.29-oracle

方法 2:MySQL 作为网络基础,WordPress 共享其网络

# 启动MySQL容器,配置数据库参数(未显式暴露端口,通过后续共享网络访问)
[root@ubuntu2004 ~]# docker run -d \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -e MYSQL_DATABASE=wordpress \
  -e MYSQL_USER=wordpress \
  -e MYSQL_PASSWORD=123456 \
  --name mysql \
  --restart=always \
  registry.cn-beijing.aliyuncs.com/xiaoming/mysql:8.0.29-oracle

# 启动WordPress容器,共享MySQL的网络命名空间(通过MySQL的网络暴露80端口)
[root@ubuntu2004 ~]# docker run -d \
  --network container:mysql \
  --name wordpress \
  --restart=always \
  registry.cn-beijing.aliyuncs.com/xiaoming/wordpress:php8.2-apache
# 注意:数据库主机地址为 127.0.0.1 wordpress 容器的 IP ,不支持 localhost

两种方法的核心区别

  • 网络共享方向不同:方法 1 中 MySQL 共享 WordPress 的网络(依赖 WordPress 暴露的 80 端口);方法 2 中 WordPress 共享 MySQL 的网络(需确保 MySQL 网络能对外提供 80 端口访问)。
  • 端口暴露方式:方法 1 显式通过-p 80:80暴露端口;方法 2 隐式通过共享网络使用端口(需注意端口冲突)。

范例:实现LNMPWordpress
# 准备配置文件
[root@ubuntu2204 ~] #cat /data/nginx/conf.d/www.wang.org.conf
server {
    listen 80;
    server_name www.wang.org;
    root /var/www/html;
    index index.php index.html index.htm;
    client_max_body_size 100m;

    location ~ \.php$ {
        root           /var/www/html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}
[root@ubuntu2204 ~] #docker run -d -p 80:80 --name wordpress -v
/data/www:/var/www/html -v /data/nginx/conf.d/:/apps/nginx/conf/conf.d/
xiaoming/nginx:1.24.0-alpine-3.18.0
[root@ubuntu2204 ~] #docker run --name php-fpm --network container:wordpress -d -
v /data/www:/var/www/html wordpress:6.2.2-php8.0-fpm-alpine
[root@ubuntu2204 ~] #docker run --name mysql --network container:wordpress -e
MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e
MYSQL_PASSWORD=123456 -d -v /data/mysql:/var/lib/mysql --restart=always
registry.cn-beijing.aliyuncs.com/xiaoming/mysql:8.0.29-oracle

范例 : 第一个容器使用 host 网络模式 , 第二个容器与之共享网络
[root@ubuntu1804 ~] #docker run -d --name c1 --network host nginx-
centos7.8:v5.0-1.18.0
5a60804f3917d82dfe32db140411cf475f20acce0fe4674d94e4557e1003d8e0
[root@ubuntu1804 ~] #docker run -it --name c2 --network container:c1
centos7.8:v1.0

6.自定义网络模式

除了以上的网络模式,也可以自定义网络,使用自定义的网段地址,网关等信息
可以使用自定义网络模式 , 实现不同集群应用的独立网络管理 , 而互不影响 , 而且在网一个网络内 , 可以直接利用容器名相互访问,非常便利

注意: 自定义网络内的容器可以直接通过容器名进行相互的访问,而无需使用 --link

1.实战案例: 自定义网络

[root@ubuntu1804 ~] #docker network create -d bridge --subnet 172.27.0.0/16 --gateway 172.27.0.1 test-net     #创建自定义网络
[root@ubuntu1804 ~] #docker network ls
NETWORK ID         NAME          DRIVER         SCOPE
cabde0b33c94       bridge             bridge             local
cb64aa83626c       host               host                 local
10619d45dcd4       none               null                 local
c90dee3b7937       test-net           bridge            local


利用自定义的网络创建容器
[root@ubuntu1804 ~]#docker run -it --rm --network test-net alpine sh
/ # ping -c1 www.baidu.com     可以ping通一次

[root@ubuntu1804 ~]#docker inspect test-net    #再开一个新终端窗口查看网络

2.实战案例: 自定义网络中的容器之间通信

[root@ubuntu1804 ~] #docker run -it --rm --network test-net --name test1 alpine sh
/ # ping -c1 test2   # 等下面步骤中容器 test2 创建好可以再访问  结果可以正常访问

[root@ubuntu1804 ~]#docker run -it --rm --network test-net --name test2 alpine sh
/ # ping -c1 test1   #能正常访问 

结论: 自定义网络中的容器之间可以直接利用容器名进行通信

3.实战案例: 利用自定义网络实现 Redis Cluster

[root@ubuntu1804 ~] #docker network create net-redis --subnet 172.18.0.0/16  创建自定义网络
[root@ubuntu1804 ~] #for port in {1..6};do              创建 6 redis 容器配置
mkdir -p /data/redis/node- ${port} /conf
cat >> /data/redis/node- ${port} /conf/redis.conf << EOF
port 6379
bind 0 .0.0.0
masterauth 123456
requirepass 123456
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172 .18.0.1 ${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

创建6 redis 容器

[root@ubuntu1804 ~] #for port in {1..6};do                    # 通过脚本运行六个 redis 容器
docker run -p 637 ${port} :6379 -p 1667 ${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 net-redis --ip 172 .18.0.1 ${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
done
创建 redis cluster
[root@ubuntu1804 ~] #docker exec -it redis-1 /bin/sh
# 创建集群
/data # redis-cli -a 123456 --cluster create 172.18.0.11:6379 172.18.0.12:6379
172.18.0.13:6379 172.18.0.14:6379 172.18.0.15:6379 172.18.0.16:6379 --cluster-replicas 1


测试访问 redis cluster

/data # redis-cli -a 123456 -c     # 连接 redis cluster
127 .0.0.1:6379> cluster info      #查看集群信息
127 .0.0.1:6379> cluster nodes
# 看到 172.18.0.{11,12,13} master,172.18.0.{14,15,16} slave
# 以下为 master/slave 关系
#172.18.0.11<--->172.18.0.15
#172.18.0.12<--->172.18.0.16
#172.18.0.13<--->172.18.0.14
127 .0.0.1:6379> set name wang     # 添加 key redis-2
172 .18.0.12:6379> set title cto    # 添加 key redis-1
172 .18.0.11:6379> get name    #结果为:wang
172 .18.0.12:6379> get title   #结果为:cto

4.同一个宿主机之间不同网络的容器通信

开两个容器,一个使用自定义网络容器,一个使用默认 brideg 网络的容器 , 默认因 iptables 规则导致无法通信。
实战案例 1: 修改iptables实现同一宿主机上的不同网络的容器间通信
[root@ubuntu1804 ~] #cat /proc/sys/net/ipv4/ip_forward   # 确认开启 ip_forward。若为1则为开启
[root@ubuntu1804 ~] #brctl show  # 默认网络和自定义网络是两个不同的网
[root@ubuntu1804 ~] #iptables -vnL
[root@ubuntu1804 ~] #iptables-save     #下面是部分截取
[root@ubuntu1804 ~] #iptables-save > iptables.rule
[root@ubuntu1804 ~] #vim iptables.rule
# 方法 1 :修改下面两行的规则
-A DOCKER-ISOLATION-STAGE-2 -o br-c90dee3b7937 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j ACCEPT
# 方法 2 :在 FORWARD 链第一行添加下面一行
-A FORWARD -j ACCEPT
# 方法 3 :执行下面命令
[root@ubuntu1804 ~] #iptables -I DOCKER-ISOLATION-STAGE-2 -j ACCEPT 【执行此】
[root@ubuntu1804 ~] #iptables-restore < iptables.rule
# 再次两个容器之间可以相互通信
实战案例 2: 通过解决docker network connect 实现同一个宿主机不同网络的容器间通信

1. 创建两个不同的 Docker 网络

打开终端,执行以下命令,创建两个不同的自定义桥接网络net1net2

docker network create net1
docker network create net2

2. 启动两个容器并分别连接到不同网络

启动容器container1并将其连接到net1网络:

docker run -d --name container1 --network net1 alpine sleep infinity

启动容器container2并将其连接到net2网络:

docker run -d --name container2 --network net2 alpine sleep infinity

此时,container1net1网络,container2net2网络,它们之间默认无法直接通信。

3. 使用 docker network connect 将容器连接到另一个网络

container1连接到net2网络:  主要步骤

docker network connect net2 container1

现在,container1同时处于net1net2两个网络中,它可以与这两个网络中的其他容器进行通信。

4. 验证容器间的通信

进入container2容器:

docker exec -it container2 sh

container2容器内,使用ping命令测试与container1的连通性,由于container1现在也在net2网络,所以可以通过容器名来 ping 通:

ping -c 3 container1

如果看到类似如下的输出,说明通信正常:

PING container1 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.078 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.070 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.070 ms

--- container1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.072/0.078 ms

同样,也可以进入container1容器,使用ping命令测试与container2的连通性:

docker exec -it container1 sh
ping -c 3 container2
实现跨宿主机的容器之间网络互联(了解)343前

十一、 Docker Compose 容器单机编排(了解)

docker-compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排,可以用它同时管理多个容器

1.安装docker compose

#Ubuntu24.04 默认需要安装 python3-pip ,否则无法启动
[root@ubuntu2404 ~] #apt update && apt install -y python3-pip
[root@ubuntu2404 ~] #apt update && apt install -y docker.io docker-compose
[root@ubuntu2404 ~] #docker-compose version  查看版本信息
查看命令格式
官方文档 : https://docs.docker.com/compose/reference/
docker compose 文件格式
官方文档 : https://docs.docker.com/compose/compose-file/

2.用 docker compose 启动多个容器

[root@ubuntu1804] #mkdir -p /data/docker-compose
[root@ubuntu1804 docker-compose] #vim docker-compose.yml
[root@ubuntu1804 docker-compose] #cat docker-compose.yml
# Nginx 服务配置(用于反向代理或静态资源服务)
service-nginx-web:
  image: 10.0.0.102/example/nginx-centos7-base:1.6.1
  container_name: nginx-web
  volumes:
    # 宿主机 /data/nginx 目录挂载到容器 /apps/nginx/html,实现静态资源持久化
    - /data/nginx:/apps/nginx/html
  expose:
    # 容器内部暴露的端口(仅用于容器间通信,不对外映射)
    - 80
    - 443
  ports:
    # 宿主机端口:容器端口,对外映射 HTTP(80) 和 HTTPS(443) 端口
    - "80:80"
    - "443:443"

# Tomcat 应用服务 1(业务应用实例 1)
service-tomcat-app1:
  image: 10.0.0.102/example/tomcat-web:app1
  container_name: tomcat-app1
  expose:
    # 容器内部暴露 Tomcat 默认端口 8080(供其他容器访问)
    - 8080
  ports:
    # 宿主机 8081 端口映射到容器 8080,对外提供 app1 访问
    - "8081:8080"

# Tomcat 应用服务 2(业务应用实例 2)
service-tomcat-app2:
  image: 10.0.0.102/example/tomcat-web:app2
  container_name: tomcat-app2
  expose:
    # 容器内部暴露 Tomcat 默认端口 8080(供其他容器访问)
    - 8080
  ports:
    # 宿主机 8082 端口映射到容器 8080,对外提供 app2 访问
    - "8082:8080"
# 在宿主机准备 nginx 测试页面文件
[root@ubuntu1804 docker-compose] #mkdir /data/nginx
[root@ubuntu1804 docker-compose] #echo Docker compose test page > /data/nginx/index.html
[root@ubuntu1804 docker-compose] #docker-compose up -d  启动容器并验证结果
[root@ubuntu1804 docker-compose] #docker-compose ps
[root@ubuntu1804 docker-compose] #curl http://127.0.0.1/      Docker compose test page
[root@ubuntu1804 docker-compose] #curl http://127.0.0.1:8081/app/   Tomcat Page in app1
[root@ubuntu1804 docker-compose] #curl http://127.0.0.1:8082/app/    Tomcat Page in app2
扩容和缩容
# 扩容
[root@ubuntu1804 docker-compose] #docker-compose scale service-nginx-web=3
# 缩容为 0 ,即删除容器
[root@ubuntu1804 docker-compose] #docker-compose scale service-nginx-web=0

十二、Docker 仓库管理

Docker 之分布式仓库 Harbor
下载 Harbor 安装包并解压缩
https://github.com/goharbor/harbor/releases

1.下载离线完整安装包,推荐使用

Harbor 下载链接: https://github.com/goharbor/harbor/releases/download/v1.10.19/harbor-offline-installer-v1.10.19.tgz

2.解压harbor前先安装docker和docker-compose

[root@ubuntu2404 ~] #apt update && apt install -y python3-pip
[root@ubuntu2404 ~] #apt update && apt install -y docker.io docker-compose

3.解压安装harbor

[root@ubuntu1804 ~] #mkdir /apps
[root@ubuntu1804 ~] #tar xf harbor-offline-installer-v1.10.19.tgz -C /usr/local
[root@ubuntu2004 ~] #vim /usr/local/harbor/harbor.yml
# 只需要修改下面两行
hostname = 10 .0.0.101           # 修改此行 , 指向当前主机 IP FQDN, 建议配置 IP
harbor_admin_password = 123456 # 修改此行指定 harbor 登录用户 admin 的密码 , 默认用户 /
:admin/Harbor12345
data_volume: /data/harbor       # 建议修改数据目录路径,使用大容量的高速磁盘,默认为 /data
# 如果不使用 https ,还需要将下面行注释掉
#https:
# port: 443
# certificate: /your/certificate/path
# private_key: /your/private/key/path
# 可选项
ui_url_protocol = http # 默认即可 , 如果修改为 https, 需要指定下面证书路径
ssl_cert = /data/cert/server.crt # 默认即可 ,https 时,需指定下面证书文件路径
ss_cert_key = /data/cert/server.key   # 默认即可 ,https 时,需指定下面私钥文件路径

4.运行 harbor 安装脚本

[root@ubuntu1804 ~] #apt -y install python        # 先安装 python
[root@ubuntu1804 ~] #/usr/local/harbor/install.sh     #运行安装脚本
[root@ubuntu1804 ~] #docker ps      # 安装 harbor 后会自动开启很多相关容器
登录 harbor 主机网站
用浏览器访问 : http://10.0.0.101/
用户名 : admin
密码 : 即前面 harbor.cfg 中指定的密码

5.使用单主机 Harbor

在项目内对用户授权,注意:至少是开发者以上才能上传镜像
命令行登录 Harbor
# 非交互登录
[root@ubuntu1804 ~] #docker login -u admin -p 123456 10.0.0.101
[root@ubuntu1804 ~] #echo 123456 | docker login -u admin --password-stdin
10.0.0.101
# 交互登录
[root@ubuntu1804 ~] #docker login 10.0.0.101
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
给本地镜像打标签并上传到 Harbor
格式为: Harbor 主机 IP/ 项目名 /image : 版本
[root@ubuntu1804 ~] #docker login 10.0.0.101   # 上传镜像前,必须先登录 harbor
[root@ubuntu1804 ~] #docker tag alpine-base:3.11 10.0.0.101/example/alpine-base:3.11
[root@ubuntu1804 ~] #docker push 10.0.0.101/example/alpine-base:3.11
# 注意 : 远程连接时 , 当前 docker 客户端的用户需要先 login harbor 上才能上传镜像
#注意:如果不事先建立项目,上传镜像失败
下载 Harbor 的镜像
下载前必须修改 docker service 文件,加入 harbor 服务器的地址才可以下载
10.0.0.103 CentOS 7 的主机上无需登录,即可下载镜像
[root@centos7 ~] #docker pull 10.0.0.101/example/centos7-base:v1    harbor 下载镜像
创建自动打标签上传镜像脚本 并登录 harbor 网站验证脚本上传镜像成功
# 10.0.0.100 上修改以前的 build.sh 脚本
[root@ubuntu1804 ~] #cd /data/dockerfile/web/nginx/1.16.1-alpine/
[root@ubuntu1804 1 .16.1-alpine] #vim build.sh
#!/bin/bash
TAG = $1
docker build -t 10 .0.0.101/example/nginx-alpine:1.16.1- ${TAG} .
docker push 10 .0.0.101/example/nginx-alpine:1.16.1- ${TAG}
docker rmi -f 10 .0.0.101/example/nginx-alpine:1.16.1- ${TAG}
[root@ubuntu1804 1 .16.1-alpine] #bash build.sh v1
修改 Harbor 配置
后期如果修改 harbor 配置,比如 : 修改 IP 地址等,可执行以下步骤生效
[root@ubuntu1804 ~] #cd /usr/local/harbor/
[root@ubuntu1804 harbor] #docker-compose stop
[root@ubuntu1804 harbor] #vim harbor.cfg # 修改 harbor 配置
[root@ubuntu1804 ~] #/usr/local/harbor/prepare   # 更新配置

6.实现 Harbor 高可用

1.安装第二台 harbor主机

在第二台主机上安装部署好 harbor ,并登录系统
注意 : 新版 harbor.yml ,旧版 harbor.cfg 中配置 hostname = 10.0.0.102

2.哪台harbor是源主机,就先在此主机上新建目标

参考第一台主机信息, 新建复制(同步)目标信息 , 将第一台主机设为复制的目标
将第一台 harbor 设为复制的目标服务器,即实现 Harbor2 harbor1 的单向复制

3 在源harbor上新建复制规则实现到目标harbor的单向复制

在第二台 harbor 上建立复制的目标主机 , 将第二台 harbor 上面的镜像复制到第一台 harbor

4.在源harbor上仓库管理中手动执行复制实现初始的同步

注意:首次只能手动执行复制才能实现全量同步,上传镜像会导致只会触发增量同步

5.在目标harbor主机上重复上面操作

以上操作,只是实现了从第二台 harbor 主机 10.0.0.102 到第一台 harbor 主机 10.0.101 的单向同步
在第一台 harbor 上再执行下面操作,才实现双向同步

6.确认同步成功

在第二台 harbor 主机上可以查看到从第一台主机同步过来的镜像和日志

7.上传镜像观察是否可以双高同步

[root@ubuntu1804 ~] #docker tag tomcat-web:app1 10.0.0.101/example/tomcat-web:app1
[root@ubuntu1804 ~] #docker push 10.0.0.101/example/tomcat-web:app1
[root@ubuntu1804 ~] #docker tag tomcat-web:app2 10.0.0.102/example/tomcat-web:app2
[root@ubuntu1804 ~] #docker push 10.0.0.102/example/tomcat-web:app2
Harbor 安全 Https 配置(略) 
相关的面试题

​1. Docker 有哪些常用指令?​

  • docker run:创建并启动一个新容器。

  • docker start/stop/restart:启动、停止、重启容器。

  • docker ps:列出运行中的容器(加 -a选项列出所有容器)。

  • docker images:列出本地镜像。

  • docker rmi:删除镜像。

  • docker rm:删除容器。

  • docker build:根据 Dockerfile 构建镜像。

  • docker pull/push:从仓库拉取或推送镜像。

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

  • docker logs:查看容器的日志输出。

  • docker network:管理网络。

  • docker volume:管理数据卷。

​2. Dockerfile 有哪些指令?​

  • FROM:指定基础镜像。

  • RUN:执行命令并创建新的镜像层,常用于安装软件包。

  • CMD:指定容器启动时默认执行的命令。

  • ENTRYPOINT:配置容器启动后执行的命令(不可被覆盖)。

  • COPY:从构建上下文复制文件到镜像中。

  • ADD:类似 COPY,但支持 URL 和自动解压压缩包。

  • ENV:设置环境变量。

  • ARG:定义构建时的变量。

  • EXPOSE:声明容器运行时监听的端口。

  • WORKDIR:设置工作目录。

  • USER:指定运行后续命令的用户。

  • VOLUME:创建挂载点(数据卷)。

​3. 两个服务器装了 Docker,双方的容器之间如何实现通信,有几种方式,不同主机的两个容器之间能够通信吗,怎么实现?​

  • ​可以通信​​。实现跨主机容器通信的主要方式有:

    • ​Overlay 网络​​: Docker 自带的 Swarm 模式或第三方网络方案(如 Calico、Flannel)可以创建覆盖网络,使不同主机上的容器仿佛在同一个局域网内。

    • ​主机网络模式​​: 使用 --net=host将容器网络直接绑定到主机网络栈上,容器通过主机IP直接通信。但此方式牺牲了隔离性。

    • ​端口映射 + 已知IP​​: 将容器端口映射到主机端口,容器通过​​对方主机的IP地址和映射出的端口​​进行通信。这是最简单但不够优雅的方式。

    • ​服务发现与负载均衡​​: 使用 Docker Swarm 或 Kubernetes 等编排工具,它们提供内置的服务发现机制,容器只需通过服务名即可访问,无需关心对方的具体IP和主机位置。

​4. Docker 的网络模式有几种?​

Docker 主要有以下几种网络模式:

  • ​bridge​​: ​​默认模式​​。为容器创建独立的网络命名空间,并通过虚拟网桥(docker0)与主机通信。容器分配私有IP,并通过NAT与外部通信。

  • ​host​​: 容器共享主机的网络命名空间,直接使用主机的IP和端口。性能最好,但网络隔离性最差。

  • ​none​​: 禁用所有网络,容器只有一个回环接口(lo),不与任何网络连接。

  • ​**​container`: 新容器共享另一个已存在容器的网络命名空间,两者网络环境完全相同。

  • ​overlay​​: 用于跨主机通信的覆盖网络,是 Docker Swarm 集群的核心网络模式。

​5. Docker的版本号是多少​

这个问题没有标准答案,因为 Docker 一直在迭代更新。您可以通过命令 docker version或 docker --version来查看您当前安装的 Docker 客户端和服务器(引擎)的具体版本号。

​6. Docker容器中如何对外映射内部的端口?​

使用 docker run命令的 -p或 -P参数。

  • -p: 将容器的内部端口映射到主机的指定端口(例如:-p 8080:80)。

  • -p: 将容器的内部端口映射到主机的随机高端口。

  • -P(大写): 自动将 Dockerfile 中 EXPOSE声明的所有端口映射到主机的随机端口。

​7. 如何找到某个 Docker容器的输出日志的宿主机位置?​

默认情况下,Docker 容器日志存储在宿主机的特定目录下。路径为:

/var/lib/docker/containers//-json.log

其中 `` 是容器的完整ID或名称。您可以使用 docker inspect命令,并查找 LogPath字段来精确找到该路径。

​8. Docker的Dockerfile中的expose端口暴露与命令执行暴露的区别​

  • EXPOSE(端口暴露)​​: 这是一个​​声明性​​的指令。它只在镜像元数据中记录容器​​运行时将会监听​​哪些端口。它​​并不会​​实际在宿主机上打开或映射这些端口。它主要用于文档说明,以及在使用 -P参数时告知 Docker 需要映射哪些端口。

  • ​命令执行暴露(-p参数)​​: 这是在​​运行容器​​时(docker run)通过 -p参数执行的​​操作​​。它完成了实际的​​端口映射​​工作,将容器内部的端口绑定到宿主机的端口上,从而使外部能够访问容器内的服务。

​9. Docker 如何查看镜像​

使用 docker images或 docker image ls命令来列出本地主机上的所有镜像。

​10. Docker 如何实现容器间互联​

  • ​通过 Docker 网络​​: 这是​​推荐的最佳实践​​。将需要通信的容器加入​​同一个自定义的 Docker 网络​​(使用 docker network create创建)。之后,容器可以通过​​容器名​​(由 --name指定)自动解析到对方的IP地址,实现互联。

  • ​通过 --link 参数​​: 旧式方法(已废弃),在 docker run时使用 --link连接另一个容器。不推荐使用,因为它功能有限且可能被移除。

​11. Docker使用到哪些技术?分别有什么作用?​

Docker 的核心技术基于 Linux 内核的特性:

  • ​Namespaces​​: 提供隔离性,包括 PID(进程)、Net(网络)、IPC(进程间通信)、Mnt(文件系统挂载)、UTS(主机名)等命名空间,使容器拥有独立的运行环境。

  • ​Cgroups​​: 提供资源限制与统计,控制和管理容器对CPU、内存、磁盘I/O等硬件资源的使用。

  • ​Union File Systems​​: 联合文件系统(如 Overlay2、AUFS),通过分层镜像和写时复制(Copy-on-Write)机制,实现镜像的轻量化和高效存储。

​12. docker run 运行一个容器,端口映射为8080,一段时间之后忘记当初运行这个容器的命令,请问如何修改映射的端口?​

  1. 首先​​停止并删除​​当前运行的容器:docker stop && docker rm

  2. 然后根据原来的镜像,使用 docker run命令并指定新的端口映射参数 -p重新运行一个容器。

    注意:无法直接修改一个已运行容器的端口映射。

​13. Dockerfile常用指令有哪些?CMD和entrypoint有什么区别?ADD和COPY有什么区别?​

  • ​常用指令​​: 参见问题2的答案。

  • ​CMD vs ENTRYPOINT​​:

    • CMD: 定义容器启动时的​​默认命令和参数​​。容易被 docker run后面接的命令行参数覆盖。

    • ENTRYPOINT: 定义容器启动时执行的​​固定命令​​。docker run后面的参数会作为参数传递给 ENTRYPOINT指令的命令。

    • 通常组合使用:ENTRYPOINT定义可执行文件,CMD定义默认参数。

  • ​ADD vs COPY​​:

    • COPY: ​​更透明、更推荐​​。仅支持将本地文件或目录从构建上下文复制到镜像中。

    • ADD: 在 COPY功能基础上,增加了:

      1. 可以从 URL 下载文件并复制到镜像中。

      2. 会自动解压压缩文件(如 tar, gzip, zip等)。

    • ​最佳实践​​: 除非确需自动解压或从远程URL添加,否则应优先使用 COPY

​14. Docker是使用什么协议进行通信的?​

Docker 守护进程(Docker Engine)默认通过 ​​Unix 套接字​​(unix:///var/run/docker.sock)与客户端(CLI)进行本地通信。也可以配置为监听 ​​TCP 端口(2375/2376)​​,使用 ​​REST API​​ 进行远程通信。2375端口为未加密的HTTP,2376端口为TLS加密的HTTPS。

​15. Dockerfile CMD,RUN 区别​

  • RUN​: 在​​构建镜像​​的过程中执行命令,并提交结果作为一个新的镜像层。常用于安装软件、创建目录等。

  • CMD​: 在​​容器启动​​时运行命令。它不会在构建过程中执行,而是指定了镜像被运行成容器后默认执行的命令。

​16. Dockerfile 做了哪些优化​

优化 Dockerfile 旨在构建更小、更安全、构建缓存更高效的镜像。

  1. ​使用合适的小体积基础镜像​​: 如 Alpine Linux 或官方提供的 -slim版本。

  2. ​合并RUN指令​​: 将多个RUN指令用 &&和 ``连接成一个,减少镜像层数。

  3. ​利用构建缓存​​: 将变化频率低的操作(如拷贝依赖管理文件package.jsonpipfile)放在 Dockerfile 前面,变化频率高的操作(如拷贝源代码)放在后面。

  4. ​使用 .dockerignore文件​​: 排除构建上下文中不必要的文件,加速构建过程和减小镜像体积。

  5. ​选择性的复制文件​​: 精确使用 COPY或 ADD,而不是复制整个构建上下文。

  6. ​使用多阶段构建​​: 将编译环境和运行环境分离,最终只将编译好的产物复制到小的运行环境镜像中,极大减小最终镜像的大小。

​17. Docker 打镜像时需不需要对容器内操作系统进行内核参数优化?​

  • ​通常不需要​​。容器与宿主机​​共享同一个内核​​,容器内部的操作系统(基础镜像)只是文件系统,其内核参数实际是​​宿主机的内核参数​​。

  • 因此,内核参数的优化应该在​​宿主机操作系统​​上进行。在容器镜像内修改内核参数通常是无效的,或者需要特权模式(--privileged)才能生效,但这会带来严重的安全风险。正确的做法是直接优化宿主机内核。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值