目录
[三. 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 的一些关键特点和优势:
-
丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用 的镜像。 例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库 的镜像。
-
官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。
-
社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。
-
版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。
-
便于搜索:用户可以通过关键词轻松搜索到所需的镜像。
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 项目。 它提供了以下主要功能和特点:
-
基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理 的灵活性。
-
镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。
-
图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。
-
审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
-
垃圾回收:可以清理不再使用的镜像,节省存储空间。
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