文章目录
- Docker简介
- Docker在企业中的应用场景
- Docker与虚拟化的对比
- Docker的优势
- 部署Docker
- 部署Docker
- Docker的基本操作
- Docker镜像管理
- 容器的常用操作
- Docker镜像构建
- Docker镜像结构
- 镜像运行的基本原理
- 镜像获得方式
- 镜像构建
- Docker镜像构建企业实例
- 镜像优化方案
- 镜像优化策略
- 镜像优化案例
- Docker镜像仓库的管理
- Docker仓库介绍
- docker hub
- Docker仓库的工作原理
- pull原理
- push原理
- 搭建Docker私有仓库
- 搭建简单的Registry仓库
- 为Registry提供加密传输
- 为仓库建立登陆认证
- 构建企业级私有仓库
- harbor简介
- 部署harbor
- Docker网络
- 原生bridge网络
- 原生网络host
- 原生网络none
- docker的自定义网络
- 自定义桥接网络
- docker容器间的网络通信
- docker跨主机网络
- CNM(Container Network Model)
- macvlan网络方式实现跨主机通信
Docker简介
- Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术,它具有以下几个重要特点和优势:
- 轻量级虚拟化
- Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。
- 例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。
- 一致性
- 确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。
- 无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。
- 可移植性
- 可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差异。
- 比如,在本地开发的容器可以无缝部署到云服务器上。
- 高效的资源利用
- 多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资源。
- 易于部署和扩展
- 能够快速部署新的应用实例,并且可以根据需求轻松地进行水平扩展。
- 轻量级虚拟化
总之,Docker 极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。它在现代软件开发和云计算领域得到了广泛的应用。
Docker在企业中的应用场景
-
在企业中docker作为业务的最小载体而被广泛应用
-
通过docker企业可以更效率的部署应用并更节省资源
IaaS(Infrastructure as a Service),即基础设施即服务
PaaS是(Platform as a Service)即指平台即服务
SaaS(Software as a Service)软件运营服务
Docker与虚拟化的对比
虚拟机 | docker容器 | |
---|---|---|
操作系统 | 宿主机上运行虚拟机OS | 共享宿主机OS |
存储 | 镜像较大(GB ) | 镜像小(MB) |
性能 | 操作系统额外的cpu、内存消耗 | 几乎无性能损耗 |
移植性 | 笨重、与虚拟化技术耦合度高 | 轻量、灵活迁移 |
隔离性 | 完全隔离 | 安全隔离 |
部署 | 慢、分钟级 | 快速、秒级 |
运行密度 | 一般几十个 | 单机支持上千容器 |
Docker的优势
-
对于开发人员:Build once、Run anywhere。
-
对于运维人员:Configure once、Run anything
-
容器技术大大提升了IT人员的幸福指数!
部署Docker
部署Docker
[root@docker-node1 ~]# ls
anaconda-ks.cfg docker.tar.gz
containerd.io-1.7.20-3.1.el9.x86_64.rpm Documents
Desktop Downloads
docker-buildx-plugin-0.16.2-1.el9.x86_64.rpm Music
docker-ce-27.1.2-1.el9.x86_64.rpm Pictures
docker-ce-cli-27.1.2-1.el9.x86_64.rpm Public
docker-ce-rootless-extras-27.1.2-1.el9.x86_64.rpm Templates
docker-compose-plugin-2.29.1-1.el9.x86_64.rpm Videos
[root@docker-node1 ~]# yum install *.rpm -y
[root@docker-node1 ~]# yum install docker-ce -y
[root@docker-node1 ~]# systemctl enable --now docker
[root@docker-node1 ~]# docker load -i game2048.tar.gz
[root@docker-node1 ~]# docker load -i nginx-latest.tar.gz
[root@docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 5ef79149e0ec 12 days ago 188MB
timinglee/game2048 latest 19299002fdbe 7 years ago 55.5MB
[root@docker-node1 ~]# docker run -d --rm --name webserver -p 80:80 nginx
d274ec6c9dfe05bbaea2c10624802bee9a32f6f8e751083b6a103bac9c9e37bb
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d274ec6c9dfe nginx "/docker-entrypoint.…" 9 seconds ago Up 8 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp webserver
[root@docker-node1 ~]# docker rm -f webserver
webserver
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker-node1 ~]# docker run -d --rm --name game1 -p 80:80 timinglee/game2048:latest
396e7333bd16d406550a19234cdc1976d5ddaaea889ba9f57b3f242702f29029
[root@docker-node1 ~]# docker rm -f game1
game1
[root@docker-node1 ~]# docker load -i mario.tar.gz
4aeeaca5ce76: Loading layer 197.2MB/197.2MB
708fd576a927: Loading layer 208.9kB/208.9kB
90222f49bc4c: Loading layer 4.608kB/4.608kB
5f70bf18a086: Loading layer 1.024kB/1.024kB
dbe97b1b7330: Loading layer 1.536kB/1.536kB
44e5704d49fb: Loading layer 9.912MB/9.912MB
Loaded image: timinglee/mario:latest
[root@docker-node1 ~]# docker load -i busybox-latest.tar.gz
d51af96cf93e: Loading layer 4.495MB/4.495MB
Loaded image: busybox:latest
[root@docker-node1 ~]# docker run -d --rm --name game2 -p 80:80 timinglee/mario:latest
62fb4d38e35435ee0d414838d5a3cb63a0b7b528d5be8f659d6ee036674634f1
Docker的基本操作
Docker镜像管理
# 搜索镜像
[root@docker-node1 ~]# docker search nginx
NAME DESCRIPTION STARS OFFICIAL
nginx Official build of Nginx. 20126 [OK]
nginx/nginx-quic-qns NGINX QUIC interop 1
参数 | 说明 |
---|---|
NAME | 镜像名称 |
DESCRIPTION | 镜像说明 |
STARS | 点赞数量 |
OFFICIAL | 是否是官方的 |
# 拉取镜像
#从镜像仓库中拉取镜像
[root@docker-node1 ~]# docker pull busybox
[root@docker-node1 ~]# docker pull nginx:1.26-alpine # alpine 版本:nginx镜像的最小安装发型版本
# 查看本地镜像
[root@docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
example v4 9af00573858d 4 hours ago 4.26MB
example v2 2dbbb3e21285 4 hours ago 4.26MB
example v3 6b6df0f84577 4 hours ago 4.26MB
example v1 f4eed4b6a9f0 4 hours ago 4.26MB
nginx latest 5ef79149e0ec 12 days ago 188MB
busybox latest 65ad0d468eb1 15 months ago 4.26MB
timinglee/game2048 latest 19299002fdbe 7 years ago 55.5MB
timinglee/mario latest 9a35a9e43e8c 8 years ago 198MB
# 查看镜像信息
[root@docker-node1 ~]# docker image inspect nginx:latest
# 导出镜像
#保存镜像
[root@Docker-node1 ~]# docker image save nginx:latest -o nginx-latest.tar.gz
[root@Docker-node1 ~]# docker image save nginx:latest nginx:1.26-alpine -o nginx.tag.gz
#保存所有镜像
[root@Docker-node1 ~]# docker save `docker images | awk 'NR>1{print $1":"$2}'` -o images.tar.gz
-o:指定导出镜像的位置;
可以同时导出多个镜像到一个文件中;
指定.tar.gz 可以导出并压缩。
# 删除镜像
[root@Docker-node1 ~]# docker rmi nginx:latest
[root@Docker-node1 ~]# docker rmi `docker images | awk 'NR>1{print $1":"$2}'`
容器的常用操作
# 启动容器
[root@Docker-node1 ~]# docker run -d --name mario -p 80:8080 timinglee/mario
#查看当前运行容器
[root@Docker-node1 ~]# docker ps
#查看所有容器
[root@Docker-node1 ~]# docker ps -a
#查看容器运行的详细信息
[root@Docker-node1 ~]# docker inspect busybox
#停止容器
[root@Docker-node1 ~]# docker stop busybox
#杀死容器
[root@Docker-node1 ~]# docker kill busybox
#开启停止的容器
[root@Docker-node1 ~]# docker start busybox
#删除停止的容器
[root@Docker-node1 ~]# docker rm centos7
#删除运行的容器
[root@Docker-node1 ~]# docker rm -f busybox
#删除所有停止的容器
[root@Docker-node1 ~]# docker container prune -f
容器内容提交
默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件
如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像
当我们在运行新镜像后即可看到我们提交的内容
[root@docker-node1 ~]# docker run -it --name test busybox
/ # touch leefile
/ # ls
bin etc leefile lib64 root tmp var
dev home lib proc sys usr
/ #
[root@docker-node1 ~]# docker rm -f test
test
[root@docker-node1 ~]# docker run -it --name test busybox
/ # ls
bin dev etc home lib lib64 proc root sys tmp usr var
/ #
[root@docker-node1 ~]# docker commit -m "add leefile" test busybox:v1
sha256:69ff2472a1ff1a75046ee767efdaabb1f32670118a05dd3f45af0aa31b6cbee6
[root@docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox v1 69ff2472a1ff 9 seconds ago 4.26MB
[root@docker-node1 ~]# docker image history busybox:v1
IMAGE CREATED CREATED BY SIZE COMMENT
69ff2472a1ff 52 seconds ago sh 8B add leefile
65ad0d468eb1 15 months ago BusyBox 1.36.1 (glibc), Debian 12 4.26MB
系统中的文件和容器中的文件传输
#把容器中的文件复制到本机
[root@docker-node1 ~]# docker cp test:/leefile /mnt
Successfully copied 1.54kB to /mnt
#把本机文件复制到容器中
[root@docker-node1 ~]# docker cp /etc/fstab test:/fstab
Successfully copied 2.56kB to test:/fstab
Docker镜像构建
Docker镜像结构
-
共享宿主机的kernel
-
base镜像提供的是最小的Linux发行版
-
同一docker主机支持运行多种Linux发行版
-
采用分层结构的最大好处是:共享资源
镜像运行的基本原理
-
Copy-on-Write 可写容器层
-
容器层以下所有镜像层都是只读的
-
docker从上往下依次查找文件
-
容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
-
一个镜像最多127层
镜像获得方式
国内可以访问的docker镜像加速器:https://docker.m.daocloud.io
openeuler操作系统的docker镜像拉取地址:https://hub.oepkgs.net
-
基本镜像通常由软件官方提供
-
企业镜像可以用官方镜像+Dockerfile来生成
-
系统关于镜像的获取动作有两种:
- docker pull 镜像地址
- docker load –i 本地镜像包
镜像构建
[root@docker-node1 ~]# mkdir docker
[root@docker-node1 ~]# cd docker/
[root@docker-node1 docker]# touch leefile
[root@docker-node1 docker]#
[root@docker-node1 docker]# vim Dockerfile
# 指定使用的基础镜像
FROM busybox:latest
# 指定作者信息
MAINTAINER qwe@example.com
# 复制当前目录文件到容器指定位置,leefile必须在当前目录中
COPY leefile /
# 构建镜像
[root@docker-node1 docker]# docker build -t example:v1 .
[+] Building 0.0s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 99B 0.0s
=> WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of u 0.0s
=> [internal] load metadata for docker.io/library/busybox:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 28B 0.0s
=> [1/2] FROM docker.io/library/busybox:latest 0.0s
=> [2/2] COPY leefile / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:f4eed4b6a9f08f469e4ec2d63c14d412497f8c5e8dc7f0568c2c68 0.0s
=> => naming to docker.io/library/example:v1 0.0s
1 warning found (use docker --debug to expand):
- MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 2)
[root@docker-node1 docker]# touch leefile{1..5}
[root@docker-node1 docker]# tar zcf leefile.gz leefile*
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest
MAINTAINER qwe@example.com
COPY leefile /
ADD leefile.gz /
[root@docker-node1 docker]# docker build -t example:v2 .
[root@docker-node1 docker]# docker run -it --rm --name test example:v2
/ # ls
bin home leefile2 leefile5 proc tmp
dev leefile leefile3 lib root usr
etc leefile1 leefile4 lib64 sys var
[root@docker-node1 docker]# vim Dockerfile
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
CMD echo $NAME
#CMD ["/bin/echo", "$NAME"]
#CMD ["/bin/sh", "-c", "/bin/echo $NAME"]
[root@docker-node1 docker]# docker build -t example:v3 .
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3
lee
[root@docker-node1 docker]# vim Dockerfile
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
ENTRYPOINT echo $NAME
# 更改完配置文件Dockerfile过后要重新build创建一下
[root@docker-node1 docker]# docker build -t example:v3 .
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3 sh
lee
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest # 指定镜像
MAINTAINER qwe@example.com # 指定作者信息
COPY leefile / # 复制文件
ADD leefile.gz / # 功能和copy相似,指定压缩文件或url
ENV NAME lee # 指定环境变量
#CMD echo $NAME # 在启动容器时自动运行动作可以被覆盖
#CMD ["/bin/echo", "$NAME"]
#CMD ["/bin/sh", "-c", "/bin/echo $NAME"]
#ENTRYPOINT echo $NAME # 和CMD功能和用法类似,但动作不可被覆盖
EXPOSE 80 443 # 暴漏容器端口
VOLUME /var/www/html # 申明数据卷,通常指数据挂载点
WORKDIR /var/www/html # 切换路径
RUN touch leefile # 在容器中运行的指令
[root@Docker-node1 docker]# docker build -t example:v4 .
[root@docker-node1 docker]# docker run -it --rm --name test example:v4
/var/www/html #
Docker镜像构建企业实例
# 导入镜像包
[root@docker-node1 ~]# ll
total 880900
-rw-r--r-- 1 root root 1244738 Aug 16 09:17 nginx-1.26.1.tar.gz
[root@docker-node1 mnt]# ll
total 206740
-rw-r--r-- 1 root root 211699200 Aug 26 19:23 centos-7.tar.gz
[root@docker-node1 mnt]# cd
[root@docker-node1 ~]# docker load -i /mnt/centos-7.tar.gz
174f56854903: Loading layer 211.7MB/211.7MB
Loaded image: centos:7
[root@docker-node1 mnt]# ls
1panel-v1.10.13-lts-linux-amd64 debian11.tar.gz leefile
1panel-v1.10.13-lts-linux-amd64.tar.gz docker nginx-1.23.tar.gz
centos-7.tar.gz hgfs nginx-1.26.1.tar.gz
[root@docker-node1 docker]# vim Dockerfile
FROM centos:7
LABEL Mail=ccc@example.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1.tar.gz
RUN yum install -y gcc make pcre-devel openssl-devel
RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]
[root@docker-node1 docker]# docker build -t nginx:v1 .
[+] Building 0.0s (6/11) docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 418B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2B 0.0s
=> [1/7] FROM docker.io/library/centos:7 0.0s
=> ERROR [2/7] ADD nginx-1.26.1.tar.gz /mnt 0.0s
------
> [2/7] ADD nginx-1.26.1.tar.gz /mnt:
------
Dockerfile:3
--------------------
1 | FROM centos:7
2 | LABEL Mail=ccc@example.com
3 | >>> ADD nginx-1.26.1.tar.gz /mnt
4 | WORKDIR /mnt/nginx-1.26.1.tar.gz
5 | RUN yum install -y gcc make pcre-devel openssl-devel
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref ec302262-d1f5-46e0-970b-e52188d86dbd::ibej66oz3wnwfuosb1sennis0: "/nginx-1.26.1.tar.gz": not found
# 解决报错
[root@docker-node1 docker]# mv /mnt/nginx-1.26.1.tar.gz .
[root@docker-node1 docker]# ls
Dockerfile nginx-1.26.1.tar.gz
# 再次构建镜像还是会报错,原因为连接网上的仓库失败,centos的镜像出现问题,为了解决这个问题,我们自己构建环境实现实验效果
[root@docker-node1 docker]# docker build -t nginx:v1 .
[root@docker-node1 docker]# dnf install httpd -y
# 修改监听端口,默认的80端口被nginx占用
[root@docker-node1 docker]# vim /etc/httpd/conf/httpd.conf
Listen 8888
[root@docker-node1 docker]# systemctl start httpd
在docker-node1主机上添加一个镜像
使用RHEL7.9的镜像
[root@docker-node1 docker]# mkdir /var/www/html/rhel7.9
[root@docker-node1 docker]# mount /dev/sr1 /var/www/html/rhel7.9/
mount: /var/www/html/rhel7.9: WARNING: source write-protected, mounted read-only.
[root@docker-node1 docker]# docker run -it --name centos centos:7
[root@53c7885f4588 /]# ls
anaconda-post.log dev home lib64 mnt proc run srv tmp var
bin etc lib media opt root sbin sys usr
[root@53c7885f4588 /]# ifconfig
bash: ifconfig: command not found
[root@53c7885f4588 /]# ip a
bash: ip: command not found
# 查看容器网络发现看不了
# 再开一个终端
[root@docker-node1 mnt]# docker inspect centos
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null,
"NetworkID": "1eb8f79c5ad647bc30d498cdb10a8510b9c884d918c2b59a279466f0c7240e5a",
"EndpointID": "89142da2c2219df6764e268a6340e67d9d0584e4116bfad91ed0233a858737fd",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DNSNames": null
# 容器网络IP为172.17.0.3
[root@docker-node1 mnt]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.142 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.072 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1035ms
rtt min/avg/max/mdev = 0.072/0.107/0.142/0.035 ms
[root@53c7885f4588 /]# cd /etc/yum.repos.d/
[root@53c7885f4588 yum.repos.d]# ls
CentOS-Base.repo CentOS-Debuginfo.repo CentOS-Sources.repo CentOS-fasttrack.repo
CentOS-CR.repo CentOS-Media.repo CentOS-Vault.repo CentOS-x86_64-kernel.repo
[root@53c7885f4588 yum.repos.d]# rm -rf *
[root@53c7885f4588 yum.repos.d]# ls
[root@53c7885f4588 yum.repos.d]# vi centos7.repo
[centos7]
name=centos7
baseurl=http://172.17.0.1:8888/rhel7.9
gpgcheck=0
[root@docker-node1 mnt]# cd
[root@docker-node1 ~]# docker commit -m "add repo" centos centos:repo
sha256:9eba96525f74fdfe6856a4bfe32d31d23202180b5f8ccb66b4b3732ad53f798c
[root@docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos repo 9eba96525f74 8 seconds ago 204MB
busybox v1 69ff2472a1ff 3 hours ago 4.26MB
example v4 9af00573858d 7 hours ago 4.26MB
example v2 2dbbb3e21285 7 hours ago 4.26MB
example v3 6b6df0f84577 7 hours ago 4.26MB
example v1 f4eed4b6a9f0 7 hours ago 4.26MB
nginx latest 5ef79149e0ec 12 days ago 188MB
busybox latest 65ad0d468eb1 15 months ago 4.26MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
timinglee/game2048 latest 19299002fdbe 7 years ago 55.5MB
timinglee/mario latest 9a35a9e43e8c 8 years ago 198MB
[root@53c7885f4588 yum.repos.d]# cd
[root@53c7885f4588 ~]# exit
exit
[root@docker-node1 docker]# docker rm centos
centos
[root@docker-node1 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=ccc@example.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install -y gcc make pcre-devel openssl-devel
RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]
[root@docker-node1 docker]# docker build -t nginx:v1 # 命令过时
[root@docker-node1 docker]# docker buildx build -t nginx:v1 /mnt/docker
[+] Building 24.8s (12/12) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 414B 0.0s
=> [internal] load metadata for docker.io/library/centos:repo 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 42B 0.0s
=> [1/7] FROM docker.io/library/centos:repo 0.0s
=> [2/7] ADD nginx-1.26.1.tar.gz /mnt 0.1s
=> [3/7] WORKDIR /mnt/nginx-1.26.1 0.0s
=> [4/7] RUN yum install -y gcc make pcre-devel openssl-devel 6.6s
=> [5/7] RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_st 3.9s
=> [6/7] RUN make 13.6s
=> [7/7] RUN make install 0.2s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:e9b2a727b4641f0e43489d1f21c27623c2dd9803aef5189b6edda55cf5316 0.0s
=> => naming to docker.io/library/nginx:v1 0.0s
镜像优化方案
镜像优化策略
-
选择最精简的基础镜像
-
减少镜像的层数
-
清理镜像构建的中间产物
-
选择最精简的基础镜像
-
减少镜像的层数
-
清理镜像构建的中间产物
镜像优化案例
# 此时构建出来的镜像大小为356MB,需要继续优化
[root@docker-node1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v1 e9b2a727b464 4 minutes ago 356MB
方案1:缩减镜像层
[root@docker-node1 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=ccc@example.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install -y gcc make pcre-devel openssl-devel && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make && make install && rm -rf /mnt/nginx-1.26.1 && yum clean all
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]
[root@docker-node1 docker]# docker buildx build -t nginx:v1 /mnt/docker
[+] Building 20.3s (9/9) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 456B 0.0s
=> [internal] load metadata for docker.io/library/centos:repo 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 42B 0.0s
=> [1/4] FROM docker.io/library/centos:repo 0.0s
=> CACHED [2/4] ADD nginx-1.26.1.tar.gz /mnt 0.0s
=> CACHED [3/4] WORKDIR /mnt/nginx-1.26.1 0.0s
=> [4/4] RUN yum install -y gcc make pcre-devel openssl-devel && ./configure --pr 20.1s
=> exporting to image 0.2s
=> => exporting layers 0.2s
=> => writing image sha256:ee52727ed92bfebf840af7586ba4462a41f9b63176a74ed7c65b508 0.0s
=> => naming to docker.io/library/nginx:v1 0.0s
[root@docker-node1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v1 ee52727ed92b 24 seconds ago 292MB
方案2:多阶段构建
[root@docker-node1 docker]# vim Dockerfile
FROM centos:repo AS build
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install -y gcc make pcre-devel openssl-devel && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make && make install && rm -rf /mnt/nginx-1.26.1 && yum clean all
FROM centos:repo
LABEL Mail=ccc@example.com
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
[root@docker-node1 docker]# docker buildx build -t nginx:v2 /mnt/docker
[+] Building 0.1s (10/10) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 532B 0.0s
=> [internal] load metadata for docker.io/library/centos:repo 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 42B 0.0s
=> CACHED [build 1/4] FROM docker.io/library/centos:repo 0.0s
=> CACHED [build 2/4] ADD nginx-1.26.1.tar.gz /mnt 0.0s
=> CACHED [build 3/4] WORKDIR /mnt/nginx-1.26.1 0.0s
=> CACHED [build 4/4] RUN yum install -y gcc make pcre-devel openssl-devel && ./co 0.0s
=> [stage-1 2/2] COPY --from=build /usr/local/nginx /usr/local/nginx 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:df2c2b56729950418b06c4245275a4aa33d87818259ffdf772218ca 0.0s
=> => naming to docker.io/library/nginx:v2 0.0s
[root@docker-node1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 df2c2b567299 27 seconds ago 210MB
nginx v1 ee52727ed92b 20 minutes ago 292MB
[root@docker-node1 docker]# docker run -d --name webserver nginx:v2
7ac92f20abea2888ffdd27eaead03ec8ca19af1426ea8f037f9c31827492a579
[root@docker-node1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7ac92f20abea nginx:v2 "/usr/local/nginx/sb…" 9 seconds ago Up 9 seconds 80/tcp webserver
方案3:使用最精简镜像
[root@docker-node1 docker]# docker exec -it webserver sh
sh-4.2#
sh-4.2# ldd /usr/local/nginx/sbin/nginx
linux-vdso.so.1 => (0x00007ffc5c9e4000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f8614ad2000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f86148b6000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f861467f000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f861441d000)
libssl.so.10 => /lib64/libssl.so.10 (0x00007f86141ab000)
libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f8613d48000)
libz.so.1 => /lib64/libz.so.1 (0x00007f8613b32000)
libc.so.6 => /lib64/libc.so.6 (0x00007f8613764000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8614cd6000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007f8613561000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f8613314000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f861302b000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f8612e27000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f8612bf4000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f86129e4000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f86127e0000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f86125c6000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f861239f000)
# 导入debian11.tar.gz包
[root@docker-node1 ~]# docker load -i debian11.tar.gz
5342a2647e87: Loading layer 327.7kB/327.7kB
577c8ee06f39: Loading layer 51.2kB/51.2kB
9ed498e122b2: Loading layer 3.379MB/3.379MB
4d049f83d9cf: Loading layer 1.536kB/1.536kB
af5aa97ebe6c: Loading layer 2.56kB/2.56kB
ac805962e479: Loading layer 2.56kB/2.56kB
bbb6cacb8c82: Loading layer 2.56kB/2.56kB
2a92d6ac9e4f: Loading layer 1.536kB/1.536kB
1a73b54f556b: Loading layer 10.24kB/10.24kB
c048279a7d9f: Loading layer 3.072kB/3.072kB
2388d21e8e2b: Loading layer 225.3kB/225.3kB
8451c71f8c1e: Loading layer 12.92MB/12.92MB
24aacbf97031: Loading layer 3.983MB/3.983MB
6835249f577a: Loading layer 1.505MB/1.505MB
Loaded image: gcr.io/distroless/base-debian11:latest
[root@docker-node1 ~]# docker load -i nginx-1.23.tar.gz
8cbe4b54fa88: Loading layer 84.01MB/84.01MB
5dd6bfd241b4: Loading layer 62.51MB/62.51MB
043198f57be0: Loading layer 3.584kB/3.584kB
2731b5cfb616: Loading layer 4.608kB/4.608kB
6791458b3942: Loading layer 3.584kB/3.584kB
4d33db9fdf22: Loading layer 7.168kB/7.168kB
Loaded image: nginx:1.23
[root@docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 df2c2b567299 19 minutes ago 210MB
nginx v1 ee52727ed92b 39 minutes ago 292MB
centos repo 9eba96525f74 About an hour ago 204MB
busybox v1 69ff2472a1ff 4 hours ago 4.26MB
example v4 9af00573858d 8 hours ago 4.26MB
example v3 6b6df0f84577 8 hours ago 4.26MB
example v2 2dbbb3e21285 8 hours ago 4.26MB
example v1 f4eed4b6a9f0 8 hours ago 4.26MB
nginx latest 5ef79149e0ec 12 days ago 188MB
nginx 1.23 a7be6198544f 15 months ago 142MB
busybox latest 65ad0d468eb1 15 months ago 4.26MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
timinglee/game2048 latest 19299002fdbe 7 years ago 55.5MB
timinglee/mario latest 9a35a9e43e8c 8 years ago 198MB
gcr.io/distroless/base-debian11 latest 2a6de77407bf N/A 20.6MB
[root@docker-node1 docker]# vim Dockerfile
FROM nginx:1.23 AS base
ARG TIME_ZONE
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
cp -a --parents /usr/share/nginx /opt && \
cp -a --parents /var/log/nginx /opt && \
cp -aL --parents /var/run /opt && \
cp -a --parents /etc/nginx /opt && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/sbin/nginx /opt && \
cp -a --parents /usr/sbin/nginx-debug /opt && \
cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
FROM gcr.io/distroless/base-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx","-g","daemon off;"]
[root@docker-node1 docker]# docker buildx build -t nginx:v3 /mnt/docker
[+] Building 0.5s (9/9) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.20kB 0.0s
=> [internal] load metadata for docker.io/library/nginx:1.23 0.0s
=> [internal] load metadata for gcr.io/distroless/base-debian11:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [base 1/2] FROM docker.io/library/nginx:1.23 0.0s
=> [stage-1 1/2] FROM gcr.io/distroless/base-debian11:latest 0.1s
=> [base 2/2] RUN mkdir -p /opt/var/cache/nginx && cp -a --parents /usr/lib/nginx 0.2s
=> [stage-1 2/2] COPY --from=base /opt / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:4df49a0f3711563a109f7fbb81d77e171e8ec746fa52d8422aeb8b1 0.0s
=> => naming to docker.io/library/nginx:v3 0.0s
[root@docker-node1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v3 4df49a0f3711 34 seconds ago 34.5MB
nginx v2 df2c2b567299 28 minutes ago 210MB
nginx v1 ee52727ed92b 48 minutes ago 292MB
[root@docker-node1 docker]# docker run --rm -d --name webserver nginx:v3
431d407456a89ff39410b900a214e0d209a2d3a29caeb6b4a9e644e7f474ff32
[root@docker-node1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
431d407456a8 nginx:v3 "nginx -g 'daemon of…" 5 seconds ago Up 4 seconds 80/tcp, 443/tcp webserver
Docker镜像仓库的管理
Docker仓库介绍
Docker仓库(Docker Registry) 是用于存储和分发 Docker 镜像的集中式存储库。
它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。
Docker 仓库可以分为公共仓库和私有仓库:
-
公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在Docker Hub 上提供的镜像,方便用户直接获取和使用。
- 例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。
-
私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。
- 比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中,以保证安全性和控制访问权限。
通过 Docker 仓库,开发者能够方便地共享和复用镜像,加速应用的开发和部署过程。
docker hub
Docker Hub 是 Docker 官方提供的一个公共的镜像仓库服务。
它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,拥有大量的官方和社区贡献的镜像。
Docker Hub 的一些关键特点和优势:
-
丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用的镜像。
- 例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库的镜像。
-
官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。
-
社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。
-
版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。
-
便于搜索:用户可以通过关键词轻松搜索到所需的镜像。
Docker仓库的工作原理
仓库中的三个角色
index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证
Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。
pull原理
镜像拉取分为以下几步:
-
docker客户端向index发送镜像拉去请求并完成与index的认证
-
index发送认证token和镜像位置给dockerclient
-
dockerclient携带token和根据index指引的镜像位置取连接registry
-
Registry会根据client持有的token跟index核实身份合法性
-
index确认此token合法性
-
Registry会根据client的请求传递镜像到客户端
push原理
镜像上传的步骤:
-
client向index发送上传请求并完成用户认证
-
index会发方token给client来证明client的合法性
-
client携带index提供的token连接Registry
-
Registry向index合适token的合法性
-
index证实token的合法性
-
Registry开始接收客户端上传过来的镜像
搭建Docker私有仓库
搭建简单的Registry仓库
# 导入registry仓库镜像包
[root@docker-node1 ~]# ls
anaconda-ks.cfg Documents
busybox-latest.tar.gz Downloads
containerd.io-1.7.20-3.1.el9.x86_64.rpm game2048.tar.gz
debian11.tar.gz mario.tar.gz
Desktop Music
docker nginx-1.23.tar.gz
docker-buildx-plugin-0.16.2-1.el9.x86_64.rpm nginx-latest.tar.gz
docker-ce-27.1.2-1.el9.x86_64.rpm Pictures
docker-ce-cli-27.1.2-1.el9.x86_64.rpm Public
docker-ce-rootless-extras-27.1.2-1.el9.x86_64.rpm registry.tag.gz
docker-compose-plugin-2.29.1-1.el9.x86_64.rpm Templates
docker.tar.gz Videos
# 下载本地registry镜像
[root@docker-node1 ~]# docker load -i registry.tag.gz
ce7f800efff9: Loading layer 7.644MB/7.644MB
30609d4f10dd: Loading layer 792.6kB/792.6kB
3b6a51496c9d: Loading layer 17.55MB/17.55MB
e704e9e3e9dc: Loading layer 3.584kB/3.584kB
f019f591461d: Loading layer 2.048kB/2.048kB
Loaded image: registry:latest
# 开启registry仓库
[root@docker-node1 ~]# docker run -d -p 5000:5000 --restart=always registry
e0c2ded04513bad47dbcd3318d98281c49801d06720e43a0ec802d61ca4190c7
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e0c2ded04513 registry "/entrypoint.sh /etc…" 5 seconds ago Up 4 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp heuristic_ptolemy
431d407456a8 nginx:v3 "nginx -g 'daemon of…" 11 hours ago Up 11 hours 80/tcp, 443/tcp webserver
# 上传镜像到仓库中
# 给要上传的镜像打标签
[root@docker-node1 ~]# docker tag nginx:v3 172.25.254.100:5000/nginx.v3
# docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
[root@docker-node1 ~]# docker push 172.25.254.100:5000/nginx.v3
Using default tag: latest
The push refers to repository [172.25.254.100:5000/nginx.v3]
Get "https://172.25.254.100:5000/v2/": context deadline exceeded
# 配置非加密端口
[root@docker-node1 ~]# vim /etc/docker/daemon.json
{
"insecure-registries" : ["http://172.25.254.100:5000"]
}
[root@docker-node1 ~]# systemctl restart docker
# 上传镜像
[root@docker-node1 ~]# docker push 172.25.254.100:5000/nginx.v3
Using default tag: latest
The push refers to repository [172.25.254.100:5000/nginx.v3]
d6dd14be2a40: Pushed
6835249f577a: Pushed
24aacbf97031: Pushed
8451c71f8c1e: Pushed
2388d21e8e2b: Pushed
c048279a7d9f: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
bbb6cacb8c82: Pushed
ac805962e479: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
9ed498e122b2: Pushed
577c8ee06f39: Pushed
5342a2647e87: Pushed
latest: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445
# 查看镜像上传
[root@docker-node1 ~]# curl 172.25.254.100:5000/v2/_catalog
{"repositories":["nginx.v3"]}
[root@docker-node1 ~]# docker tag busybox:latest 172.25.254.100:5000/busybox:latest
[root@docker-node1 ~]# docker push 172.25.254.100:5000/busybox:latest
The push refers to repository [172.25.254.100:5000/busybox]
d51af96cf93e: Pushed
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
[root@docker-node1 ~]# curl 172.25.254.100:5000/v2/_catalog
{"repositories":["busybox","nginx.v3"]}
为Registry提供加密传输
# 生成认证key和证书
# 首先清空这个/etc/docker/daemon.json文件,然后重启docker
[root@docker-node1 ~]# mkdir certs
# 添加本地解析
[root@docker-node1 ~]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.100 docker-node1.example.com
172.25.254.100 reg.example.com
[root@docker-node1 ~]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/example.com.key -addext "subjectAltName = DNS:reg.example.com" -x509 -days 365 -out certs/example.com.crt
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shaanxi
Locality Name (eg, city) [Default City]:XiAn
Organization Name (eg, company) [Default Company Ltd]:docker
Organizational Unit Name (eg, section) []:reg
Common Name (eg, your name or your server's hostname) []:reg.example.com
Email Address []:sdmin@example.com
# 启动registry仓库
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/example.com.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/example.com.key registry:latest
25c40876824680b6ab95e9ccc5e05b261ec77f87678f180f2f28f4685d7ebff9
[root@docker-node1 ~]# docker tag nginx:v3 reg.example.com/nginx:v3
[root@docker-node1 ~]# mkdir -p /etc/docker/certs.d/reg.example.com
[root@docker-node1 ~]# cp /root/certs/example.com.crt /etc/docker/certs.d/reg.example.com/ca.crt
[root@docker-node1 ~]# systemctl restart docker
# 测试
[root@docker-node1 ~]# docker push reg.example.com/nginx:v3
The push refers to repository [reg.example.com/nginx]
d6dd14be2a40: Pushed
6835249f577a: Pushed
24aacbf97031: Pushed
8451c71f8c1e: Pushed
2388d21e8e2b: Pushed
c048279a7d9f: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
bbb6cacb8c82: Pushed
ac805962e479: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
9ed498e122b2: Pushed
577c8ee06f39: Pushed
5342a2647e87: Pushed
v3: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c4e83697100b registry:latest "/entrypoint.sh /etc…" 2 minutes ago Up 2 minutes 0.0.0.0:443->443/tcp, :::443->443/tcp, 5000/tcp reverent_sinoussi
为仓库建立登陆认证
# 安装建立认证文件的工具包
[root@docker-node1 ~]# dnf install httpd-tools -y
# 建立认证文件
[root@docker-node1 ~]# mkdir auth
# -B 强制使用最安全加密方式,默认用md5加密
[root@docker-node1 ~]# htpasswd -Bc auth/.htpasswd aaa
New password:
Re-type new password:
Adding password for user aaa
[root@docker-node1 ~]# htpasswd -B auth/.htpasswd ccc
New password:
Re-type new password:
Adding password for user ccc
[root@docker-node1 ~]# cat auth/.htpasswd
aaa:$2y$05$rRsbthyl5O.tUI5fx/9PPuG/.tE0gKF73yGAj73b9vnf6eKzPC1IK
ccc:$2y$05$hvP/5rkwGaXJqkczD/IP6uWbq6JNo5QgPUungPNst8M19cAyRS7oS
# 添加认证到registry容器中
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/example.com.crt -e REGISTRY_HTTP_TLS_KEY=/certs/example.com.key -v /root/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/.htpasswd registry:latest
a23c532ef791ade2276f9cf354924c5d207703872add0bf1ec1e7c21904bf04a
# 登录测试
[root@docker-node1 ~]# docker login reg.example.com
Username: aaa
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
[root@docker-node1 ~]# docker push reg.example.com/nginx:v3
The push refers to repository [reg.example.com/nginx]
d6dd14be2a40: Pushed
6835249f577a: Pushed
24aacbf97031: Pushed
8451c71f8c1e: Pushed
2388d21e8e2b: Pushed
c048279a7d9f: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
bbb6cacb8c82: Pushed
ac805962e479: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
9ed498e122b2: Pushed
577c8ee06f39: Pushed
5342a2647e87: Pushed
v3: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445
[root@docker-node1 ~]# curl -k https://172.25.254.100/v2/_catalog -uaaa:aaa
{"repositories":["nginx"]}
构建企业级私有仓库
harbor简介
Harbor 是由vmware公司开源的企业级 Docker Registry 项目。
它提供了以下主要功能和特点:
-
基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理的灵活性。
-
镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。
-
图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。
-
审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
-
垃圾回收:可以清理不再使用的镜像,节省存储空间。
部署harbor
# 导入软件包并解压
[root@docker-node1 ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker-node1 ~]# cd harbor/
[root@docker-node1 harbor]# ls
common.sh harbor.v2.5.4.tar.gz harbor.yml.tmpl install.sh LICENSE prepare
[root@docker-node1 harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker-node1 harbor]#
[root@docker-node1 harbor]# vim harbor.yml
hostname: reg.example.com
certificate: /data/certs/example.com.crt
private_key: /data/certs/example.com.key
harbor_admin_password: 111
[root@docker-node1 harbor]# ./install.sh --help
Note: Please set hostname and other necessary attributes in harbor.yml first. DO NOT use localhost or 127.0.0.1 for hostname, because Harbor needs to be accessed by external clients.
Please set --with-notary if needs enable Notary in Harbor, and set ui_url_protocol/ssl_cert/ssl_cert_key in harbor.yml bacause notary must run under https.
Please set --with-trivy if needs enable Trivy in Harbor
Please set --with-chartmuseum if needs enable Chartmuseum in Harbor
[root@docker-node1 harbor]# ./install.sh --with-chartmuseum
[root@docker-node1 harbor]# cp /root/certs/ /data/ -r
[root@docker-node1 harbor]# ls /data/
certs secret
[root@docker-node1 harbor]# ./install.sh --with-chartmuseum
✔ ----Harbor has been installed and started successfully.----
[root@docker-node1 harbor]# cd
[root@docker-node1 ~]# docker logout reg.example.com
Removing login credentials for reg.example.com
[root@docker-node1 ~]# docker login reg.example.com
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
# 上传镜像
[root@docker-node1 ~]# docker tag nginx:v3 reg.example.com/aaa/nginx:v3
[root@docker-node1 ~]# docker push reg.example.com/aaa/nginx:v3
The push refers to repository [reg.example.com/aaa/nginx]
d6dd14be2a40: Pushed
6835249f577a: Pushed
24aacbf97031: Pushed
8451c71f8c1e: Pushed
2388d21e8e2b: Pushed
c048279a7d9f: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
bbb6cacb8c82: Pushed
ac805962e479: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
9ed498e122b2: Pushed
577c8ee06f39: Pushed
5342a2647e87: Pushed
v3: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445
Docker网络
docker安装后会自动创建3种网络:bridge、host、none
在做实验之前把防火墙策略默认选择为iptables,并将网络还原
[root@docker-node1 ~]# grubby --update-kernel ALL --args iptables=true
[root@docker-node1 ~]# reboot
[root@docker-node1 ~]# cd harbor/
[root@docker-node1 harbor]# docker compose down
WARN[0000] /root/harbor/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 12/12
✔ Container registryctl Removed 0.0s
✔ Container harbor-jobservice Removed 0.0s
✔ Container chartmuseum Removed 0.0s
✔ Container nginx Removed 0.0s
✔ Container harbor-portal Removed 0.1s
✔ Container harbor-core Removed 0.0s
✔ Container harbor-db Removed 0.1s
✔ Container registry Removed 0.1s
✔ Container redis Removed 0.2s
✔ Container harbor-log Removed 10.1s
✔ Network harbor_harbor-chartmuseum Removed 0.1s
✔ Network harbor_harbor Removed 0.2s
[root@docker-node1 harbor]# docker network ls
NETWORK ID NAME DRIVER SCOPE
69a4dc8c8489 bridge bridge local
4bd953d7c4ac host host local
c9977c22ee4e none null local
原生bridge网络
docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口
bridge模式下容器没有公有ip,只有宿主机可以直接访问,外部主机是不可见的。
容器通过宿主机的NAT规则后可以访问外网。
[root@docker-node1 harbor]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker-node1 harbor]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER 0 -- 0.0.0.0/0 0.0.0.0/0
DOCKER-ISOLATION-STAGE-1 0 -- 0.0.0.0/0 0.0.0.0/0
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
DOCKER 0 -- 0.0.0.0/0 0.0.0.0/0
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 0 -- 0.0.0.0/0 0.0.0.0/0
RETURN 0 -- 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target prot opt source destination
DROP 0 -- 0.0.0.0/0 0.0.0.0/0
RETURN 0 -- 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN 0 -- 0.0.0.0/0 0.0.0.0/0
[root@docker-node1 harbor]# cd
[root@docker-node1 ~]# docker run -it --name webserver --network bridge busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2042 (1.9 KiB) TX bytes:0 (0.0 B)
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)
/ # ping www.baidu.com
PING www.baidu.com (36.155.132.76): 56 data bytes
64 bytes from 36.155.132.76: seq=0 ttl=127 time=28.611 ms
64 bytes from 36.155.132.76: seq=1 ttl=127 time=27.987 ms
^C
--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 27.987/28.299/28.611 ms
/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
/ # exit
# ping通外网,网关为172.17.0.1,这个IP为docker0的ip
[root@docker-node1 ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:9ff:fe08:baaf prefixlen 64 scopeid 0x20<link>
ether 02:42:09:08:ba:af txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 28 bytes 4257 (4.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.100 netmask 255.255.255.0 broadcast 172.25.254.255
inet6 fe80::710e:6c55:6c39:99f6 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:2d:14:17 txqueuelen 1000 (Ethernet)
RX packets 714 bytes 68603 (66.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 676 bytes 208341 (203.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# 查看iptables策略 MASQUERADE地址伪装,把宿主机当成一个路由器,docker0负责接受所有容器的请求,然后再通过内核路由功能到达eth0,然后进行地址伪装,伪装成172.25.254.100
[root@docker-node1 ~]# iptables -t nat -nL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE 0 -- 172.17.0.0/16 0.0.0.0/0
原生网络host
host网络模式需要在容器创建时指定 --network=host
host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性
[root@docker-node1 ~]# docker rm webserver
webserver
[root@docker-node1 ~]# docker run -it --rm --name test --network host busybox
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:09:08:BA:AF
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:9ff:fe08:baaf/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:34 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:342 (342.0 B) TX bytes:4771 (4.6 KiB)
eth0 Link encap:Ethernet HWaddr 00:0C:29:2D:14:17
inet addr:172.25.254.100 Bcast:172.25.254.255 Mask:255.255.255.0
inet6 addr: fe80::710e:6c55:6c39:99f6/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1379 errors:0 dropped:0 overruns:0 frame:0
TX packets:1113 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:139041 (135.7 KiB) TX bytes:251685 (245.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:254 errors:0 dropped:0 overruns:0 frame:0
TX packets:254 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:21559 (21.0 KiB) TX bytes:21559 (21.0 KiB)
host网络模式直接使用真机的网络
如果公用一个网络,那么所有的网络资源都是公用的,比如启动了nginx容器那么真实主机的80端口被占用,在启动第二个nginx容器就会失败
原生网络none
none模式是指禁用网络功能,只有lo接口,在容器创建时使用
--network=none
指定。
[root@docker-node1 ~]# docker run -it --rm --name test --network none busybox
/ # ifconfig
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)
docker的自定义网络
自定义网络模式,docker提供了三种自定义网络驱动:
-
bridge
-
overlay
-
macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能
overlay和macvlan是用于创建跨主机网络
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址
自定义桥接网络
自定义桥接模式中有dns模块,但是默认的桥接模式中没有。
[root@docker-node1 ~]# docker run -it --name test --network bridge busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2318 (2.2 KiB) TX bytes:0 (0.0 B)
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)
[root@docker-node1 ~]# docker run -it --name test1 --network bridge busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1370 (1.3 KiB) TX bytes:0 (0.0 B)
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)
此时test的ip地址为172.17.0.2,test1的为172.17.0.3。现在exit退出两个容器再做测试。
[root@docker-node1 ~]# docker start test1
test1
[root@docker-node1 ~]# docker attach test1
/ #
/ #
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:18 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2388 (2.3 KiB) TX bytes:0 (0.0 B)
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)
[root@docker-node1 ~]# docker start test
test
[root@docker-node1 ~]# docker attach test
/ #
/ #
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2058 (2.0 KiB) TX bytes:0 (0.0 B)
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)
现在test1的ip变为了172.17.0.2,现在test的ip变为了172.17.0.3。这样就会出现一个问题,通信的时候ip出现变化就会导致访问出现问题。虽然ip会发生变化,但是不变的是容器名称,所以在容器或者k8s当中都是用容器名称进行通信,而不是用ip地址进行通信。
# 此时发现在test容器里面ping172.24.254.2这个ip的时候是通的,但是ping容器名称test1是不通的,这说明原生的bridge桥接模式当中没有dns模块。所以需要自定义桥接模式使用容器名称进行通信。
/ # ping test1
ping: bad address 'test1'
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.136 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.095 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.095/0.115/0.136 ms
# 自定义桥接网络
[root@docker-node1 ~]# docker network create net1 -d bridge
b1f98aa77ceb2f23774e2fb54058258cc3ff753b9186b249245b05ad91409d6d
[root@docker-node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
69a4dc8c8489 bridge bridge local
4bd953d7c4ac host host local
b1f98aa77ceb net1 bridge local
c9977c22ee4e none null local
[root@docker-node1 ~]# docker rm test
test
[root@docker-node1 ~]# docker rm test1
test1
[root@docker-node1 ~]# docker run -it --name test --network net1 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:37 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:5454 (5.3 KiB) TX bytes:0 (0.0 B)
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)
# 通过容器的名字可以进行通信
/ # ping test1
PING test1 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.230 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.105 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.089 ms
^C
--- test1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.089/0.141/0.230 ms
[root@docker-node1 ~]# docker run -it --name test1 --network net1 busybox
docker容器间的网络通信
[root@docker-node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
69a4dc8c8489 bridge bridge local
4bd953d7c4ac host host local
c9977c22ee4e none null local
[root@docker-node1 ~]# docker network create net1 -d bridge
d1171761c571ab344654280888b79890bd2979de5ff252945e82f07c155a3e36
[root@docker-node1 ~]# docker network create net2 -d bridge
cdc5e0c9a785597c0f94435aec6434efe9466ef841307b17015a27acef804efb
[root@docker-node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
69a4dc8c8489 bridge bridge local
4bd953d7c4ac host host local
d1171761c571 net1 bridge local
cdc5e0c9a785 net2 bridge local
c9977c22ee4e none null local
[root@docker-node1 ~]# docker run -it --name test --network net1 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:26 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3636 (3.5 KiB) TX bytes:0 (0.0 B)
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)
[root@docker-node1 ~]# docker run -it --name test1 --network net2 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:13:00:02
inet addr:172.19.0.2 Bcast:172.19.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:30 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:4324 (4.2 KiB) TX bytes:0 (0.0 B)
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)
/ # ping test
ping: bad address 'test'
# 此时两个网络之间不能进行通信
# 实现容器两个网络栈之间的通信
[root@docker-node1 ~]# docker network connect net1 test1
[root@docker-node1 ~]# docker run -it --name test1 --network net2 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:13:00:02
inet addr:172.19.0.2 Bcast:172.19.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:47 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:6360 (6.2 KiB) TX bytes:364 (364.0 B)
eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:03
inet addr:172.18.0.3 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2198 (2.1 KiB) TX bytes:0 (0.0 B)
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:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:710 (710.0 B) TX bytes:710 (710.0 B)
/ # ping test
PING test (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.236 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.143 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.094 ms
^C
--- test ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.094/0.157/0.236 ms
joined容器网络
Joined容器一种较为特别的网络模式,在容器创建时使用–network=container:vm1指定。(vm1指定的是运行的容器名)
处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
两个容器用同一个网络栈实现通信
[root@docker-node1 ~]# docker rm test test1
test
test1
[root@docker-node1 ~]# docker run -it --name test --network net1 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:14 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1836 (1.7 KiB) TX bytes:0 (0.0 B)
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)
[root@docker-node1 ~]# docker run -it --name test1 --network container:test busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:20 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2528 (2.4 KiB) TX bytes:0 (0.0 B)
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)
[root@docker-node1 ~]# docker rm test test1
test
test1
[root@docker-node1 ~]# docker run -d --name test --network net1 nginx
ca6cf1bc6e1f889ec915da614aa582914efb3856dabac6fa5a6ea0676921f0bf
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ca6cf1bc6e1f nginx "/docker-entrypoint.…" 3 seconds ago Up 3 seconds 80/tcp test
[root@docker-node1 ~]# docker run -it --name test1 --network container:test centos:7
# centos:7 通过回环接口进行通信
[root@ca6cf1bc6e1f /]# curl localhost
<!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>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@docker-node1 ~]# docker stop test
test
[root@docker-node1 ~]# docker rm test test1
# 利用容器部署phpmyadmin管理mysql
# 导入mysql-5.7.tar.gz和phpmyadmin-latest.tar.gz
[root@docker-node1 ~]# docker load -i mysql-5.7.tar.gz
cff044e18624: Loading layer 145MB/145MB
7ff7abf4911b: Loading layer 11.26kB/11.26kB
8b2952eb02aa: Loading layer 2.383MB/2.383MB
d76a5f910f6b: Loading layer 13.91MB/13.91MB
8527ccd6bd85: Loading layer 7.168kB/7.168kB
4555572a6bb2: Loading layer 3.072kB/3.072kB
0d9e9a9ce9e4: Loading layer 79.38MB/79.38MB
532b66f4569d: Loading layer 3.072kB/3.072kB
337ec6bae222: Loading layer 278.8MB/278.8MB
73cb62467b8f: Loading layer 17.41kB/17.41kB
441e16cac4fe: Loading layer 1.536kB/1.536kB
Loaded image: mysql:5.7
[root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz
4cae4ea97049: Loading layer 3.584kB/3.584kB
7f0d23b78477: Loading layer 320.2MB/320.2MB
8f42af1dd50e: Loading layer 5.12kB/5.12kB
7285b46fc0b1: Loading layer 51.28MB/51.28MB
886076bbd0e5: Loading layer 9.728kB/9.728kB
fe49c1c8ccdc: Loading layer 7.68kB/7.68kB
c98461c57e2d: Loading layer 13.41MB/13.41MB
4646cbc7a84d: Loading layer 4.096kB/4.096kB
7183cf0cacbe: Loading layer 49.48MB/49.48MB
923288b71444: Loading layer 12.8kB/12.8kB
eb4f3a0b1a71: Loading layer 4.608kB/4.608kB
43cd9aa62af4: Loading layer 4.608kB/4.608kB
9f9985f7ecbd: Loading layer 9.134MB/9.134MB
25d63a36933d: Loading layer 6.656kB/6.656kB
13ccf69b5807: Loading layer 53.35MB/53.35MB
a65e8a0ad246: Loading layer 8.192kB/8.192kB
26f3cdf867bf: Loading layer 3.584kB/3.584kB
Loaded image: phpmyadmin:latest
# 运行phpmysqladmin
[root@docker-node1 ~]# docker run -d --name mysqladmin --network net1 \
> -e PMA_ARBITRARY=1 \
> -p 80:80 phpmyadmin:latest
1a7d0cb189d69c508451149316c1313f1a1809e9d30ab506c5c8b48f02faf470
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a7d0cb189d6 phpmyadmin:latest "/docker-entrypoint.…" 18 seconds ago Up 17 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp mysqladmin
# 运行mysql
[root@docker-node1 ~]# docker run -d --name mysql --network container:mysqladmin \
> -e MYSQL_ROOT_PASSWORD='123' \
> mysql:5.7
cdeeebbb71ba4b4c0e60ae497ae605126bb68342b987ff3c4c107915bbda2d5d
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cdeeebbb71ba mysql:5.7 "docker-entrypoint.s…" 3 seconds ago Up 3 seconds mysql
1a7d0cb189d6 phpmyadmin:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp mysqladmin
[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# mysql -uroot -p123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 5.7.44 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
docker跨主机网络
在生产环境中,我们的容器不可能都在同一个系统中,所以需要容器具备跨主机通信的能力
- 跨主机网络解决方案
- docker原生的overlay和macvlan
- 第三方的flannel、weave、calico
- 众多网络方案是如何与docker集成在一起的
- libnetwork docker容器网络库
- CNM (Container Network Model)这个模型对容器网络进行了抽象
CNM(Container Network Model)
CNM分三类组件
Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)
Endpoint:作用是将sandbox接入network (veth pair)
Network:包含一组endpoint,同一network的endpoint可以通信
macvlan网络方式实现跨主机通信
macvlan网络方式
- Linux kernel提供的一种网卡虚拟化技术。
- 无需Linux bridge,直接使用物理接口,性能极好
- 容器的接口直接与主机网卡连接,无需NAT或端口映射。
- macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
- vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094
macvlan网络间的隔离和连通
-
macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的
-
可以在三层上通过网关将macvlan网络连通起来
-
docker本身不做任何限制,像传统vlan网络那样管理即可
# docker-node2上安装docker
[root@docker-node2 ~]# ls
anaconda-ks.cfg Desktop Documents Music Public Videos
busybox-latest.tar.gz docker.tar.gz Downloads Pictures Templates
[root@docker-node2 ~]# tar zxf docker.tar.gz
[root@docker-node2 ~]# ls
anaconda-ks.cfg docker.tar.gz
busybox-latest.tar.gz Documents
containerd.io-1.7.20-3.1.el9.x86_64.rpm Downloads
Desktop Music
docker-buildx-plugin-0.16.2-1.el9.x86_64.rpm Pictures
docker-ce-27.1.2-1.el9.x86_64.rpm Public
docker-ce-cli-27.1.2-1.el9.x86_64.rpm Templates
docker-ce-rootless-extras-27.1.2-1.el9.x86_64.rpm Videos
docker-compose-plugin-2.29.1-1.el9.x86_64.rpm
[root@docker-node2 ~]# dnf install *.rpm -y
[root@docker-node2 ~]# systemctl enable --now docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
[root@docker-node2 ~]# docker load -i busybox-latest.tar.gz
d51af96cf93e: Loading layer 4.495MB/4.495MB
Loaded image: busybox:latest
# 在docker-node1和docker-node2两台主机上各添加一张网卡,设为仅主机模式,打开混杂模式
[root@docker-node2 ~]# ip link set eth1 promisc on
[root@docker-node2 ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
ether 00:0c:29:1e:8b:4c txqueuelen 1000 (Ethernet)
RX packets 3 bytes 288 (288.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
[root@docker-node2 ~]# docker network create -d macvlan --subnet 4.4.4.0/24 --gateway 4.4.4.4 -o parent=eth1 mynet1
d91e357f1521a7d7fe0cdd427745b54870ff10b79c8275856aec0c68ee4baa37
[root@docker-node2 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
c8e7cb428485 bridge bridge local
0b46b496c786 host host local
d91e357f1521 mynet1 macvlan local
7af801f50a8b none null local
[root@docker-node2 ~]# docker run -it --name test --network mynet1 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:04:04:04:01
inet addr:4.4.4.1 Bcast:4.4.4.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 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:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
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)
[root@docker-node1 ~]# ip link set eth1 promisc on
[root@docker-node1 ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
ether 00:0c:29:2d:14:21 txqueuelen 1000 (Ethernet)
RX packets 3 bytes 288 (288.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
[root@docker-node1 ~]# docker network create -d macvlan --subnet 4.4.4.0/24 \
> --gateway 4.4.4.4 \
> -o parent=eth1 mynet1
278ee54437519d7d0f135be91a440306a2f9d89734549ff6fb067db205404db7
[root@docker-node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
69a4dc8c8489 bridge bridge local
4bd953d7c4ac host host local
278ee5443751 mynet1 macvlan local
c9977c22ee4e none null local
[root@docker-node1 ~]# docker run -it --name test --network mynet1 --ip 4.4.4.2 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:04:04:04:02
inet addr:4.4.4.2 Bcast:4.4.4.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 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:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
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)
# 测试
/ # ping 4.4.4.1
PING 4.4.4.1 (4.4.4.1): 56 data bytes
64 bytes from 4.4.4.1: seq=0 ttl=64 time=1.302 ms
64 bytes from 4.4.4.1: seq=1 ttl=64 time=0.340 ms
^C
--- 4.4.4.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.340/0.821/1.302 ms
/ #