Docker 进阶构建:镜像与仓库管理

目录

[三. docker镜像构建](#三. docker镜像构建)

[1. docker镜像结构](#1. docker镜像结构)

[2. 镜像运行的基本原理](#2. 镜像运行的基本原理)

[3. 镜像获得方式](#3. 镜像获得方式)

[4. 镜像构建](#4. 镜像构建)

[5. Dockerfile实例](#5. Dockerfile实例)

[6. 镜像优化方案](#6. 镜像优化方案)

[6.1. 镜像优化策略](#6.1. 镜像优化策略)

[6.2. 镜像优化示例:缩减镜像层](#6.2. 镜像优化示例:缩减镜像层)

[6.3. 镜像优化示例:多阶段构建](#6.3. 镜像优化示例:多阶段构建)

[6.4. 镜像优化示例:使用最精简镜像](#6.4. 镜像优化示例:使用最精简镜像)

[四. docker 镜像仓库的管理](#四. docker 镜像仓库的管理)

[1. 什么是docker仓库](#1. 什么是docker仓库)

[2. docker hub](#2. docker hub)

[3. docker hub的使用方法](#3. docker hub的使用方法)

[3. docker仓库的工作原理](#3. docker仓库的工作原理)

[4. pull原理](#4. pull原理)

[5. push原理](#5. push原理)

[6. 搭建docker的私有仓库](#6. 搭建docker的私有仓库)

[6.1. 为什么搭建私有仓库](#6.1. 为什么搭建私有仓库)

[6.2. 搭建简单的Registry仓库](#6.2. 搭建简单的Registry仓库)

[6.3. 为Registry提加密传输](#6.3. 为Registry提加密传输)

[6.4. 为仓库建立登陆认证](#6.4. 为仓库建立登陆认证)

[7. 构建企业级私有仓库](#7. 构建企业级私有仓库)

[7.1. 部署harbor](#7.1. 部署harbor)

[7.2. 管理仓库](#7.2. 管理仓库)

[五. Docker 网络](#五. Docker 网络)

[1. docker原生bridge网路](#1. docker原生bridge网路)

[2. docker原生网络host](#2. docker原生网络host)

[3. docker 原生网络none](#3. docker 原生网络none)

[4. docker的自定义网络](#4. docker的自定义网络)

[4.1. 自定义桥接网络](#4.1. 自定义桥接网络)

[4.2. 为什么要自定义桥接](#4.2. 为什么要自定义桥接)

[4.3. 如何让不同的自定义网络互通?](#4.3. 如何让不同的自定义网络互通?)

[4.4. joined容器网络](#4.4. joined容器网络)

[4.5. joined网络示例演示](#4.5. joined网络示例演示)

[5. 容器内外网的访问](#5. 容器内外网的访问)

[5.1 容器访问外网](#5.1 容器访问外网)

[5.2 外网访问docker容器](#5.2 外网访问docker容器)

[6. docker跨主机网络](#6. docker跨主机网络)

[6.1 CNM (Container Network Model)](#6.1 CNM (Container Network Model))

[6.2 macvlan网络方式实现跨主机通信](#6.2 macvlan网络方式实现跨主机通信)


三. docker镜像构建

1. docker镜像结构
  • 共享宿主机的kernel

  • base镜像提供的是最小的Linux发行版

  • 同一docker主机支持运行多种Linux发行版

  • 采用分层结构的最大好处是:共享资源

2. 镜像运行的基本原理
  • Copy-on-Write 可写容器层

  • 容器层以下所有镜像层都是只读的

  • docker从上往下依次查找文件

  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改一个镜像最多127层

3. 镜像获得方式
  • 基本镜像通常由软件官方提供

  • 企业镜像可以用官方镜像+Dockerfile来生成

  • 系统关于镜像的获取动作有两种:

  • docker pull 镜像地址

  • docker load --i 本地镜像包

4. 镜像构建
bash 复制代码
#FROM COPY 和MAINTAINER
[root@Docker-node1 ~]# mkdir docker/
[root@Docker-node1 ~]# cd docker/
[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile   #基础镜像
[root@Docker-node1 docker]# docker build -t busybox:v1 . #构建镜像
[root@Docker-node1 docker]# docker images history busybox:v1
[root@Docker-node1 docker]#docker run -it --rm --name test1 busybox:v1

[root@Docker-node1 docker]# mv Dockerfile timinglee
[root@Docker-node1 docker]# docker build -f /root/docker/timinglee -t example:v2 .    #-f指定名字
[root@Docker-node1 docker]# docker images

[root@Docker-node1 docker]# mv timinglee Dockerfile
[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org    #rhel版本不一样,指令不同 #指定邮箱信息
[root@Docker-node1 docker]# docker build -t busybox:v2 .
[root@Docker-node1 docker]#docker images history busybox:v2

cp /etc/passwd
[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org
COPY passwd /passwd  #复制当前目录文件到容器指定位置,passwd必须在当前目录中
[root@Docker-node1 docker]#docker build -t busybox:v3 .
[root@Docker-node1 docker]#docker images history busybox:v3
[root@Docker-node1 docker]#docker run -it --rm --name test busybox:v3 #启动进入文件,看对应目录有没有文件
#如果已存在可以,删掉docker rm -f test

[root@Docker-node1 docker]# tar zcf zhuzhuxia.tar.gz Dockerfile passwd
[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org
COPY passwd /passwd
ADD zhuzhuxia.tar.gz /mnt
[root@Docker-node1 docker]# docker build -t busybox:v4 .
[root@Docker-node1 docker]# docker run -it --rm --name tes busybox:v4

[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org
COPY passwd /passwd
ADD zhuzhuxia.tar.gz /mnt
RUN mkdir /lee
[root@Docker-node1 docker]# docker build -t busybox:v5 .
[root@Docker-node1 docker]# docker images history busybox:v5
[root@Docker-node1 docker]# docker run -it --rm --name test busybox:v5

[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org
COPY passwd /passwd
ADD zhuzhuxia.tar.gz /mnt
RUN mkdir /lee
CMD ["/bin/sh", "-c", "echo hello lee"]   #CMD的不同写法
#CMD echo joker
[root@Docker-node1 docker]# docker build -t busybox:v6 .
[root@Docker-node1 docker]# docker images history busybox:v6
[root@Docker-node1 docker]# docker run -it --name test busybox:v6

[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org
COPY passwd /passwd
ADD zhuzhuxia.tar.gz /mnt
RUN mkdir /lee
ENV name=timinglee
ENTRYPOINT ["/bin/sh", "-c", "echo xiaofeifei"]   #不可替代
CMD ["/bin/sh", "-c", "echo $NAME"]   #CMD被替代
[root@Docker-node1 docker]# docker build -t busybox:v6 .
[root@Docker-node1 docker]# docker images history busybox:v6
[root@Docker-node1 docker]# docker run -it --rm --name test busybox:v6  #有内容;CMD
[root@Docker-node1 docker]# docker rm test
[root@Docker-node1 docker]# docker run -it --rm --name test busybox:v6 sh  #无内容;CMD
[root@Docker-node1 docker]# docker run -it --rm --name test busybox:v6 sh  #有内容;测试ENTRYPOINT

[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org
COPY passwd /passwd
ADD zhuzhuxia.tar.gz /mnt
RUN mkdir /lee
EXPOSE 80 443   #暴露端口
ENV name=timinglee
ENTRYPOINT ["/bin/sh", "-c", "sleep 10000000"]   #不可替代
CMD ["/bin/sh", "-c", "echo $NAME"]   #CMD被替代
[root@Docker-node1 docker]# docker build -t busybox:v6 .
[root@Docker-node1 docker]# docker run -it --rm --name test busybox:v6  
[root@Docker-node1 docker]# docker run -d --rm --name test busybox:v6 
[root@Docker-node1 docker]# docker ps #看端口
[root@Docker-node1 docker]# docker stop test

[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
RUN touch /leefile 
LABEL Mail=lee@timinglee.org
COPY passwd /passwd
ADD zhuzhuxia.tar.gz /mnt
RUN mkdir /lee
EXPOSE 80 443
WORKDIR /mnt   #工作目录
VOLUME /lee   #目录挂载
[root@Docker-node1 docker]# docker build -t busybox:v6 .
[root@Docker-node1 docker]# docker run -it --rm --name test busybox:v6  
[root@Docker-node1 docker]# docker inspect test  #看"Mounts"的下面有没有目录/lee
5. Dockerfile实例
bash 复制代码
#清理容器
[root@node9 ~]# docker images
[root@node9 ~]# docker rmi <IMAGE ID> 
[root@node9 ~]# docker rmi `docker images | awk '/none/{print $1}'`
[root@node9 ~]# docker rmi busybox:v{1..7}

#可以先拖入企业7镜像centos和nginx1.26软件包,提前下载。
[root@node9 ~]# docker load -i /mnt/centos-7

#建立构建目录,编写构建文件
[root@node9 ~]# mdkir docker
[root@node9 ~]# cd docker/
[root@node9 docker]# mv /nginx-1.26.1.tar.gz . #移动文件到当前。
[root@node9 docker]# vim Dockerfile
FROM centos:7
LABEL Mail=lee@timinglee.org
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"]

#通过dockerfile生成镜像
[root@node9 docker]# docker build -t nginx:v1 

#出现仓库报错,添加一个rhel7.9镜像虚拟机。
#添加一个端口
[root@node9 docker]# yum install httpd -y
[root@node9 docker]# vim /etc/httpd/conf/httpd.conf
...
listen 8888
...
[root@node9 docker]# systemctl start httpd

#挂载端口
[root@node9 docker]# mkdir /var/www/html/rhel7.9
[root@node9 docker]# mount /dev/sr1 /var/www/html/rhel7.9

#查看ip
[root@node9 docker]# docker inspect centos:7
[root@node9 docker]# ping 172.17.0.2

#进入容器
[root@node9 docker]# docker run -it --name centos centos:7
cd /etc/yum.repos.d/
rm -fr *
vim centos7.repo
[centos7]
name=centos7
baseurl=http://172.17.0.1:8888/rhel7.9
gpgcheck=0

#将一个名为 "centos" 的容器创建一个新的镜像,并为新镜像添加注释信息 "add repo",新镜像命名为 "centos:repo"
[root@node9 docker]# docker commit -m "add repo" centos centos:repo
[root@node9 docker]# docker rm centos

#修改配置文件
[root@node9 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=lee@timinglee.org
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@node9 docker]# docker build -t nginx:v1 

#查看容器
[root@server1 docker]# docker images
6. 镜像优化方案
6.1. 镜像优化策略
  • 选择最精简的基础镜像

  • 减少镜像的层数

  • 清理镜像构建的中间产物

  • 选择最精简的基础镜像

  • 减少镜像的层数

  • 清理镜像构建的中间产物

6.2. 镜像优化示例:缩减镜像层
bash 复制代码
[root@node9 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=lee@timinglee.org
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 -fr nginx-
1.26.1 && yum clean all
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off"]   #CMD 是 Dockerfile 中的一个指令,用于定义容器启动时默认执行的命令。
["/usr/local/nginx/sbin/nginx", "-g", "daemon off"]:这是一个命令列表。其中,/usr/local/nginx/sbin/nginx 是启动 Nginx 服务器的命令路径。-g 是 Nginx 的全局配置指令参数,daemon off 表示以非守护进程模式运行 Nginx,即让 Nginx 在前台运行,这样容器就不会在启动 Nginx 后立即退出,而是保持运行状态直到容器被停止或者出现错误。

[root@node9 docker]# docker build -t nginx:v2 .
[root@node9 docker]# docker images nginx
[root@node9 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=lee@timinglee.org
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 -fr nginx-
1.26.1 && yum clean all
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off"]   #CMD 是 Dockerfile 中的一个指令,用于定义容器启动时默认执行的命令。
["/usr/local/nginx/sbin/nginx", "-g", "daemon off"]:这是一个命令列表。其中,/usr/local/nginx/sbin/nginx 是启动 Nginx 服务器的命令路径。-g 是 Nginx 的全局配置指令参数,daemon off 表示以非守护进程模式运行 Nginx,即让 Nginx 在前台运行,这样容器就不会在启动 Nginx 后立即退出,而是保持运行状态直到容器被停止或者出现错误。

[root@node9 docker]# docker build -t nginx:v2 .
[root@node9 docker]# docker images nginx
6.3. 镜像优化示例:多阶段构建
bash 复制代码
[root@node9 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 -fr nginx-
1.26.1 && yum clean all

FROM centos:repo
LABEL Mail=lee@timinglee.org
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@node9 docker]# docker build -t nginx:v3 .
[root@node9 docker]# docker images nginx
6.4. 镜像优化示例:使用最精简镜像

使用google提供的最精简镜像

bash 复制代码
#下载地址:
https://github.com/GoogleContainerTools/distroless

#下载镜像:
docker pull gcr.io/distroless/base
#提前下载,直接拖入即可。

#利用最精简镜像构建
[root@node9 docker]# vim Dockerfile
FROM nginx:1.23 AS base
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
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@node9 ~]# docker build -t nginx:v4 .
[root@node9 ~]# docker images nginx
测试:
[root@node9 ~]# docker run --rm -d --name wevserver nginx:v4
[root@node9 ~]# docker ps

四. docker 镜像仓库的管理

1. 什么是docker仓库

Docker 仓库(Docker Registry) 是用于存储和分发 Docker 镜像的集中式存储库。 它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉 取所需的镜像。 Docker 仓库可以分为公共仓库和私有仓库: 公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在 Docker Hub 上提供的镜像,方便用户直接获取和使用。 例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。 私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。 比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中, 以保证安全性和控制访问权限。 通过 Docker 仓库,开发者能够方便地共享和复用镜像,加速应用的开发和部署过程。

2. docker hub

官网:https://hub.docker.com/ Docker Hub 是 Docker 官方提供的一个公共的镜像仓库服务。 它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,拥有大量的官方和社区贡献的镜像。 以下是 Docker Hub 的一些关键特点和优势:

  1. 丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用 的镜像。 例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库 的镜像。

  2. 官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。

  3. 社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。

  4. 版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。

  5. 便于搜索:用户可以通过关键词轻松搜索到所需的镜像。

3. docker hub的使用方法
bash 复制代码
#登陆官方仓库
[root@docker ~]# docker login
Log in with your Docker ID or email address to push and pull images from Docker
Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to
create one.
You can log in with your password or a Personal Access Token (PAT). Using a
limited-scope PAT grants better security and is required for organizations using
SSO. Learn more at https://docs.docker.com/go/access-tokens/
Username: timinglee
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 ~]# cd .docker/
[root@docker .docker]# ls
config.json
[root@docker .docker]# cat config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "dGltaW5nbGVlOjY3NTE1MTVtaW5nemxu"
		}
	}
}

[root@docker ~]# docker tag nginx:v3 timinglee/nginx:v3   #修改名字,类似索引

[root@docker ~]# docker push timinglee/nginx:v3
3. docker仓库的工作原理

仓库中的三个角色

  • index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。

  • registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证

  • Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。

4. pull原理

镜像拉取分为以下几步: 1.docker客户端向index发送镜像拉去请求并完成与index的认证 2.index发送认证token和镜像位置给dockerclient 3.dockerclient携带token和根据index指引的镜像位置取连接registry 4.Registry会根据client持有的token跟index核实身份合法性 5.index确认此token合法性 6.Registry会根据client的请求传递镜像到客户端

5. push原理

镜像上传的步骤: 1.client向index发送上传请求并完成用户认证 2.index会发方token给client来证明client的合法性 3.client携带index提供的token连接Registry 4.Registry向index合适token的合法性 5.index证实token的合法性 6.Registry开始接收客户端上传过来的镜像

6. 搭建docker的私有仓库
6.1. 为什么搭建私有仓库

docker hub虽然方便,但是还是有限制

  • 需要internet连接,速度慢

  • 所有人都可以访问

  • 由于安全原因企业不允许将镜像放到外网

好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库 地址: https://docs.docker.com/registry/deploying/

6.2. 搭建简单的Registry仓库
bash 复制代码
#下载Registry镜像
[root@node9 ~]#  docker pull registry
#我是提前下载了,所以直接拖入。
[root@node9 ~]# 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@node9 ~]# docker run -d -p 5000:5000 --restart=always --name registry registry
338896d1cc20d7e06ef39a0a3351b71b2a91b81dcfb12cae1818efd646fd05b4
[root@node9 ~]# docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED              STATUS              PORTS                                       NAMES
338896d1cc20   registry                 "/entrypoint.sh /etc..."   About a minute ago   Up About a minute   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
d571fb7d7d7c   timinglee/mario:latest   "python3 -m http.ser..."   14 hours ago         Up 14 hours         0.0.0.0:80->8080/tcp, :::80->8080/tcp       game2

#上传镜像到仓库中
#给要上传的镜像大标签
[root@node9 ~]# docker tag nginx:latest 172.25.254.100:5000/nginx:latest

#docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
[root@node9 ~]# docker push 172.25.254.100:5000/nginx:latest
The push refers to repository [172.25.254.100:5000/nginx]
Get "https://172.25.254.100:5000/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

#配置非加密端口
[root@node9 ~]# cat /etc/docker/daemon.json 
{
	"insecure-registries":["http://172.25.254.100:5000"]
}
[root@node9 ~]# systemctl restart docker

#上传镜像
[root@node9 ~]# docker push 172.25.254.100:5000/nginx:latest
The push refers to repository [172.25.254.100:5000/nginx]
5f0272c6e96d: Pushed 
f4f00eaedec7: Pushed 
55e54df86207: Pushed 
ec1a2ca4ac87: Pushed 
8b87c0c66524: Pushed 
72db5db515fd: Pushed 
9853575bc4f9: Pushed 
latest: digest: sha256:127262f8c4c716652d0e7863bba3b8c45bc9214a57d13786c854272102f7c945 size: 1778

#查看镜像上传
[root@node9 ~]# curl 172.25.254.100:5000/v2/_catalog
{"repositories":["nginx"]}
6.3. 为Registry提加密传输
bash 复制代码
#走加密端口
[root@node9 ~]# cat /etc/docker/daemon.json  #内容清掉。
[root@node9 ~]# systemctl restart docker

#本地解析
vim /etc/hosts
172.25.254.100  node9.timinglee.org

#生成认证key和证书
[root@node9 ~]# mkdir -p certs
[root@node9 ~]# openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \ #指定备用名称
-x509 -days 365 -out certs/timinglee.org.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]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:timinglee
Organizational Unit Name (eg, section) []:docker
Common Name (eg, your name or your server's hostname) []:reg.timinglee.org
Email Address []:admin@timinglee.org

#启动registry仓库
[root@docker ~]# docker run -d -p 443:443 --restart=always --name registry \
> --name registry -v /opt/registry:/var/lib/registry \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key registry
[root@node9 ~]# docker rm -f registry
registry
[root@node9 ~]# docker ps

测试:
docker tag busybox:latest reg.timinglee.org/busybox:latest
[root@docker docker]# docker push reg.timinglee.org/busybox:latest #docker客户端没有key和证书
Error response from daemon: Get "https://reg.timinglee.org/v2/": tls: failed toverify certificate: x509: certificate signed by unknown authority

#为客户端建立证书
[root@docker docker]# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
[root@docker docker]# cp /root/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
[root@docker docker]# systemctl restart docker
[root@node9 ~]# docker push reg.timinglee.org/busybox:latest
The push refers to repository [reg.timinglee.org/busybox]
d51af96cf93e: Pushed 
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
[root@docker docker]# curl -k https://reg.timinglee.org/v2/_catalog
{"repositories":["busybox"]}
6.4. 为仓库建立登陆认证
bash 复制代码
#安装建立认证文件的工具包
[root@docker docker]# dnf install httpd-tools -y

#建立认证文件
[root@docker ~]# mkdir auth
[root@docker ~]# htpasswd -Bc auth/htpasswd lee #-B 强制使用最安全加密方式,默认用md5加密
New password:
Re-type new password:
Adding password for user timinglee

#添加认证到registry容器中
[root@docker ~]# docker run -d -p 443:443 --restart=always --name registry \
> --name registry -v /opt/registry:/var/lib/registry \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key \
> -v /root/auth:/auth \
> -e "REGISTRY_AUTH=htpasswd" \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
> registry

#允许 curl 连接到使用自签名证书的服务器(-k 表示忽略 SSL 证书验证)。-u lee:123 用于提供用户名 lee 和密码 123 进行基本身份验证。从指定的 URL 获取数据,并以 JSON 格式返回了一个包含 repositories 数组的响应,数组中包含了 busybox 和 nginx
[root@docker ~]# curl -k https://node9.timinglee.org/v2/_catalog -u lee:123
{"repositories":["busybox","nginx"]}
  
#当仓库开启认证后必须登陆仓库才能进行镜像上传
#未登陆情况下上传镜像
[root@node9 ~]# docker push reg.timinglee.org/nginx
Using default tag: latest
The push refers to repository [reg.timinglee.org/nginx]
5f0272c6e96d: Preparing 
f4f00eaedec7: Preparing 
55e54df86207: Preparing 
ec1a2ca4ac87: Preparing 
8b87c0c66524: Preparing 
72db5db515fd: Preparing 
9853575bc4f9: Preparing 
no basic auth credentials

#未登陆请款下也不能下载
[root@node9 ~]# docker tag nginx:latest reg.timinglee.org/nginx
[root@node9 ~]# docker push reg.timinglee.org/nginx
[root@node9 ~]# docker pull reg.timinglee.org/nginx
Using default tag: latest
Error response from daemon: Head "https://reg.timinglee.org/v2/nginx/manifests/latest": no basic auth credentials

#登陆测试
[root@docker ~]# docker login reg.timinglee.org
Username: lee
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

#退出登录
docker logout reg.timinglee.org
7. 构建企业级私有仓库

下载软件包地址 Releases · goharbor/harbor · GitHub Harbor 是由vmware公司开源的企业级 Docker Registry 项目。 它提供了以下主要功能和特点:

  1. 基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理 的灵活性。

  2. 镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。

  3. 图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。

  4. 审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。

  5. 垃圾回收:可以清理不再使用的镜像,节省存储空间。

7.1. 部署harbor
bash 复制代码
#提前下载,直接解压。
[root@docker ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker ~]# ls
anaconda-ks.cfg certs harbor-offline-installer-v2.5.4.tgz
auth harbor
cp -r /root/certs/ /data/
[root@docker ~]# cd harbor/
[root@docker harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker harbor]# vim harbor.yml
hostname: reg.timinglee.org
certificate: /data/certs/timinglee.org.crt
private_key: /data/certs/timinglee.org.key
harbor_admin_password: 123
[root@docker harbor]# ./install.sh --help
Please set --with-notary #证书签名
Please set --with-trivy #安全扫描
Please set --with-chartmuseum if needs enable Chartmuseum in Harbor
[root@docker harbor]# ./install.sh --with-chartmuseum

#管理harbor的容器
[root@docker harbor]# docker compose stop   #停止
[root@docker harbor]# docker compose up -d   #重新加载
7.2. 管理仓库
bash 复制代码
#Windows本地解析
172.25.254.100  reg.timinglee.org

#在浏览器上访问172.25.254.100
1.登陆;账号:admin 密码:123
2.建立仓库项目 项目名字:xiaozhuhzu,#在后面拉取镜像时需要加上这个标签

#上传镜像
[root@docker harbor]# docker login reg.timinglee.org
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@node9 ~]# docker tag busybox:latest reg.timinglee.org/xiaozhuzhu/busybox:v1
[root@node9 ~]# docker push reg.timinglee.org/xiaozhuzhu/busybox:v1
The push refers to repository [reg.timinglee.org/xiaozhuzhu/busybox]
d51af96cf93e: Pushed 
v1: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
测试:
在浏览器上查看上传的镜像

五. Docker 网络

docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分 docker安装后会自动创建3种网络:bridge、host、none

bash 复制代码
#切换模式iptables
grubby --update-kernel ALL --args iptables=true

#查看network
[root@node9 ~]# docker network ls
NETWORK ID     NAME                        DRIVER    SCOPE
0f5f6bc4bbf6   bridge                      bridge    local
ea9a34a2492b   harbor_harbor               bridge    local
1b13291bf8c7   harbor_harbor-chartmuseum   bridge    local
1b469e272a9a   host                        host      local
ce6ef696809d   none                        null      local

#清理一些不用的网络
cd harbor/
docker compose down
1. docker原生bridge网路

docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口

bash 复制代码
[root@node9 ~]# ip link show type bridge
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 02:42:e0:53:92:60 brd ff:ff:ff:ff:ff:ff
12: br-1b13291bf8c7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:7a:e8:5f:36 brd ff:ff:ff:ff:ff:ff
13: br-ea9a34a2492b: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:d1:58:69:b4 brd ff:ff:ff:ff:ff:ff

bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。 容器通过宿主机的NAT规则后可以访问外网

bash 复制代码
[root@docker mnt]# docker run -d --name web -p 80:80 nginx:1.23
defeba839af1b95bac2a200fd1e06a45e55416be19c7e9ce7e0c8daafa7dd470
[root@docker mnt]# ifconfig
....
veth7f320e9: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::986b:99ff:fe19:f8d9  prefixlen 64  scopeid 0x20<link>
        ether 9a:6b:99:19:f8:d9  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 21  bytes 2556 (2.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth7f320e9 为容器使用的网卡
#软件包bridge-utils-1.5-9.el7.x86_64
[root@docker mnt]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02425fe2346c no veth022a7c9
2. docker原生网络host

host网络模式需要在容器创建时指定 --network=host host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

bash 复制代码
[root@docker ~]# docker run -it --name test --network host busybox
/ # ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:E0:53:92:60  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:e0ff:fe53:9260/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8335 errors:0 dropped:0 overruns:0 frame:0
          TX packets:10143 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:4402060 (4.1 MiB)  TX bytes:71967675 (68.6 MiB)

eth0      Link encap:Ethernet  HWaddr 00:0C:29:70:64:35  
          inet addr:172.25.254.100  Bcast:172.25.254.255  Mask:255.255.255.0
          inet6 addr: fe80::f21f:eb6:d618:77cb/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:538105 errors:0 dropped:0 overruns:0 frame:0
          TX packets:42952 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:773168166 (737.3 MiB)  TX bytes:13541075 (12.9 MiB)

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:11834 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11834 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1045343 (1020.8 KiB)  TX bytes:1045343 (1020.8 KiB)

veth7f320e9 Link encap:Ethernet  HWaddr 9A:6B:99:19:F8:D9  
          inet6 addr: fe80::986b:99ff:fe19:f8d9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:2696 (2.6 KiB)

如果公用一个网络,那么所有的网络资源都是公用的,比如启动了nginx容器那么真实主机的80端口被占用,在启动第二个nginx容器就会失败
3. docker 原生网络none

none模式是指禁用网络功能,只有lo接口,在容器创建时使用 --network=none指定。

bash 复制代码
[root@docker ~]# docker run -it --name test --rm --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)
4. docker的自定义网络

自定义网络模式,docker提供了三种自定义网络驱动:

bridge overlay macvlan bridge驱动类似默认的bridge网络模式,但增加了一些新的功能, overlay和macvlan是用于创建跨主机网络 建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。

4.1. 自定义桥接网络
bash 复制代码
#在建立自定以网络时,默认使用桥接模式
[root@node9 ~]# docker network create my_net1
3c765727244e0bf1e19ee4c6539232e51eea30a115b36ce5ae908ea4833d9c1d
[root@node9 ~]# docker network ls
NETWORK ID     NAME                        DRIVER    SCOPE
0f5f6bc4bbf6   bridge                      bridge    local
1b469e272a9a   host                        host      local
3c765727244e   my_net1                     bridge    local
ce6ef696809d   none                        null      local

#桥接默认是单调递增
[root@docker ~]# ifconfig
br-1b13291bf8c7: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:7aff:fee8:5f36  prefixlen 64  scopeid 0x20<link>
        ether 02:42:7a:e8:5f:36  txqueuelen 0  (Ethernet)
        RX packets 8335  bytes 4402060 (4.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10143  bytes 71967675 (68.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

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:e0ff:fe53:9260  prefixlen 64  scopeid 0x20<link>
        ether 02:42:e0:53:92:60  txqueuelen 0  (Ethernet)
        RX packets 8335  bytes 4402060 (4.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10143  bytes 71967675 (68.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

#桥接也支持自定义子网和网关
[root@node9 ~]# docker network create my_net2 --subnet 192.168.0.0/24 --gateway 192.168.0.100
2d17ab32024ae8d4272650c7ac0fe9aada6e7acb93409e35a29ff30b8a610382
[root@node9 ~]# docker network inspect my_net2
[
    {
        "Name": "my_net2",
        "Id": "2d17ab32024ae8d4272650c7ac0fe9aada6e7acb93409e35a29ff30b8a610382",
        "Created": "2024-08-28T16:28:22.122754722+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/24",
                    "Gateway": "192.168.0.100"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
4.2. 为什么要自定义桥接
bash 复制代码
[root@docker ~]# docker run -d --name web1 nginx
d5da7eaa913fa6cdd2aa9a50561042084eca078c114424cb118c57eeac473424
[root@docker ~]# docker run -d --name web2 nginx
0457a156b02256915d4b42f6cc52ea71b18cf9074ce550c886f206fef60dfae5
[root@docker ~]# docker inspect web1
"Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null,
                    "NetworkID": "7abac7f53cd3e9f8c9ec6cca5d736f390f4ccd326852a3b61e8c42f8953b94ac",
                    "EndpointID": "65d7c1a72a48499e4b5c361305bcb8e7054b37626ec5d5de70d7395ba6f5baa7",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",      #注意ip信息
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DNSNames": null

[root@docker ~]# docker inspect web1
    "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null,
                    "NetworkID": "7abac7f53cd3e9f8c9ec6cca5d736f390f4ccd326852a3b61e8c42f8953b94ac",
                    "EndpointID": "26a3af63c8c7d97ea722a6bc25220d5ad73157dcf58f9e7df8a1b7639ae0ed8e",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",   #注意ip信息
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DNSNames": null

#关闭容器后重启容器,启动顺序调换
[root@docker ~]# docker stop web1 web2
web1
web2
[root@docker ~]# docker start web2
web2
[root@docker ~]# docker start web1
web1
#我们会发容器ip颠倒

docker引擎在分配ip时时根据容器启动顺序分配到,谁先启动谁用,是动态变更的
多容器互访用ip很显然不是很靠谱,那么多容器访问一般使用容器的名字访问更加稳定
docker原生网络是不支持dns解析的,自定义网络中内嵌了dns

[root@docker ~]# docker run -d --network my_net1 --name web3 nginx
d9ed01850f7aae35eb1ca3e2c73ff2f83d13c255d4f68416a39949ebb8ec699f
[root@docker ~]# docker run -it --network my_net1 --name test busybox
/ # ping web3
PING web (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.197 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.096 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.087 ms

注意:不同的自定义网络是不能通讯的
#在rhel7中使用的是iptables进行网络隔离,在rhel9中使用nftpables
[root@docker ~]# nft list ruleset可以看到网络隔离策略
4.3. 如何让不同的自定义网络互通?
bash 复制代码
[root@node9 ~]# docker network create mynet1 -d bridge
b7251c3df5a0094a5a6e46ed0b95b28c340f3fc07c582bd21b1466828b58a55c
[root@node9 ~]# docker network create mynet2 -d bridge
9feb3fab05a8dca230e76d49722a8d819c0134c473b2d01935ce3a5b482e6499
[root@node9 ~]# docker run -it --name testone --network mynet1 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:32 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:4597 (4.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@node9 ~]# docker run -it --name testtwo --network mynet2 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:36 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:5244 (5.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: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 testone
ping: bad address 'testone'   #没有执行指令ping不通
/ # ifconfig                    #执行指令多一个网卡,可以ping
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:45 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:6154 (6.0 KiB)  TX bytes:380 (380.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: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:2016 (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: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:794 (794.0 B)  TX bytes:794 (794.0 B)

/ # ping testone
PING testone (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.145 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.146 ms
^C
--- testone ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.145/0.145/0.146 ms

#在上面test容器中加入网络eth1
[root@node9 ~]# docker network connect mynet1 testtwo
4.4. joined容器网络

Joined容器一种较为特别的网络模式,•在容器创建时使用--network=container:vm1指定。(vm1指定的是运行的容器名) 处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。

bash 复制代码
[root@node9 ~]# docker rm testone
testone
[root@node9 ~]# docker rm testtwo
testtwo
[root@node9 ~]# docker run -it --name testone --network mynet1 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: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:2007 (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)

[root@node9 ~]# docker run -it --name testtwo --network container:testone  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  #注意看ip信息
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:19 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:2416 (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@node9 ~]# docker rm testone
testone
[root@node9 ~]# docker rm testtwo
testtwo

[root@node9 ~]# docker run -d --name testone --network mynet1 nginx
[root@node9 ~]# docker run -it --name testtwo --network container:testone centos:7
[root@b526153da4e6 /]# 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>
4.5. joined网络示例演示

利用容器部署phpmyadmin管理mysql

bash 复制代码
#提前下载mysql包
[root@node9 ~]# docker load -i phpmyadmin-latest.tar.gz 
[root@node9 ~]# docker load -i mysql-5.7.tar.gz 

#运行phpmysqladmin
[root@docker ~]# docker run -d --name mysqladmin --network mynet1 \
-e PMA_ARBITRARY=1 \     #在web页面中可以手动输入数据库地址和端口
-p 80:80 phpmyadmin:latest

#运行数据库
[root@docker ~]# docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD='123' \ #设定数据库密码
--network container:mysqladmin \ #把数据库容器添加到phpmyadmin容器中
mysql:5.7

测试:
在浏览器访问172.25.254.100。在hphmyadmin界面新建mysql。

#登录docker的mysql
docker exec -it mysql bash
mysql -uroot -p123
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| peihua316          |
| performance_schema |
| sys                |
| yangcun            |
| zhuzhuxia          |
+--------------------+
7 rows in set (0.00 sec)
mysql> SHOW TABLES FROM peihua316;
+---------------------+
| Tables_in_peihua316 |
+---------------------+
| 316                 |
+---------------------+
1 row in set (0.00 sec)
mysql> select * from peihua316.316;
+------+-------+------+-------+
| yaos | caimb | xies | liups |
+------+-------+------+-------+
| 2    | 3     | 1    | 4     |
+------+-------+------+-------+
1 row in set (0.01 sec)

Note
开启的phpmyadmin容器中是没有数据库的
这里填写的localhost:3306是因为mysql容器和phpmyadmin容器公用一个网络站
5. 容器内外网的访问
5.1 容器访问外网

在rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网 在rhel7之后的版本中通过nftables添加地址伪装来访问外网。

bash 复制代码
#清理网络环境,回到原来的网络环境
[root@node9 ~]# docker rm -f mysql
[root@node9 ~]# docker rm -f mysqladmin
[root@node9 ~]# docker network rm mynet2
mynet2
[root@node9 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
540ffd549691   bridge    bridge    local
1b469e272a9a   host      host      local
ce6ef696809d   none      null      local

#切换模式iptables
grubby --update-kernel ALL --args iptables=true   #之前配置过就不用再配置。iptables是为了看效果,一般不用这个。

#启动一个网络
[root@node9 ~]# docker run --rm -it --name test 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: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:1728 (1.6 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=27.229 ms   #这里可以先ping可不可以通,之后再关掉iptables -t nat -D POSTROUTING 1 这个协议,再ping一下。
[root@node9 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0 #内网访问外网策略
Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80
5.2 外网访问docker容器

端口映射 -p 本机端口:容器端口来暴漏端口从而达到访问效果。

bash 复制代码
#通过docker-proxy对数据包进行内转
[root@docker ~]# docker run -d --name webserver --rm -p 80:80 nginx
[root@node9 ~]# ps ax | grep proxy
   3572 ?        Sl     0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 80
   3578 ?        Sl     0:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 80 -container-ip 172.17.0.2 -container-port 80
   3666 pts/1    S+     0:00 grep --color=auto proxy

#通过dnat策略来完成浏览内转,有双保险。
[root@node9 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0           
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:80

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:8

#删掉DNAT,再外面curl 172.25.254.100。应该是通的。因为有双保险。
iptables -t nat -D DOCKER 2
iptables -t nat -nL
[root@node9 ~]# curl 172.25.254.100
6. docker跨主机网络

在生产环境中,我们的容器不可能都在同一个系统中,所以需要容器具备跨主机通信的能力 跨主机网络解决方案 docker原生的overlay和macvlan 第三方的flannel、weave、calico 众多网络方案是如何与docker集成在一起的 libnetwork docker容器网络库 CNM (Container Network Model)这个模型对容器网络进行了抽象

6.1 CNM (Container Network Model)

CNM分三类组件 Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace) Endpoint:作用是将sandbox接入network (veth pair) Network:包含一组endpoint,同一network的endpoint可以通信

6.2 macvlan网络方式实现跨主机通信

macvlan网络方式

  • Linux kernel提供的一种网卡虚拟化技术。

  • 无需Linux bridge,直接使用物理接口,性能极好

  • 容器的接口直接与主机网卡连接,无需NAT或端口映射。

  • macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络

  • vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094

macvlan网络间的隔离和连通

  • macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的

  • 可以在三层上通过网关将macvlan网络连通起来

  • docker本身不做任何限制,像传统vlan网络那样管理即可 实现方法如下:

bash 复制代码
#在两台docker主机上各添加一块网卡,设置仅主机模式,开启混杂模式:
#一台:172.25.254.100 双网卡  一台:172.25.254.200  双网卡
#两台机子都要有docker;提前下载busybox镜像包。
#172.25.254.100    #两台机子都需要打开模式
[root@docker ~]# ip link set eth1 promisc on
[root@docker ~]# ip link set up eth1
[root@docker ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
ether 00:0c:29:ec:fc:dd txqueuelen 1000 (Ethernet)
RX packets 83 bytes 8696 (8.4 KiB)
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

#添加macvlan网路;#两台机子都需要添加
[root@docker ~]# docker network create \
-d macvlan \
--subnet 4.4.4.0/24 \
--gateway 4.4.4.4 \
-o parent=eth1 macvlan1
[root@docker ~]# docker network ls

#测试
#在172.25.254.100中
[root@docker ~]# docker run -it --rm --name busybox --network macvlan1 --ip 4.4.4.2 busybox
/ # ifconfig
/ # ping 4.4.4.1
#在172.25.254.200中
[root@docker-node2 ~]# docker run -it --name busybox --network macvlan1 --ip 1.1.1.200 --rm busybox
/ # ifconfig
相关推荐
东华果汁哥8 分钟前
【linux 免密登录】快速设置kafka01、kafka02、kafka03 三台机器免密登录
linux·运维·服务器
咖喱鱼蛋29 分钟前
Ubuntu安装Electron环境
linux·ubuntu·electron
ac.char33 分钟前
在 Ubuntu 系统上安装 npm 环境以及 nvm(Node Version Manager)
linux·ubuntu·npm
肖永威39 分钟前
CentOS环境上离线安装python3及相关包
linux·运维·机器学习·centos
tian2kong42 分钟前
Centos 7 修改YUM镜像源地址为阿里云镜像地址
linux·阿里云·centos
Code_Artist42 分钟前
使用Portainer来管理并编排Docker容器
docker·云原生·容器
mengao123444 分钟前
centos 服务器 docker 使用代理
服务器·docker·centos
布鲁格若门1 小时前
CentOS 7 桌面版安装 cuda 12.4
linux·运维·centos·cuda
Eternal-Student1 小时前
【docker 保存】将Docker镜像保存为一个离线的tar归档文件
运维·docker·容器
网络安全-杰克1 小时前
网络安全概论
网络·web安全·php