当前位置: 首页 > news >正文

企业级 Docker 应用:部署、仓库与安全加固

1 Docker简介及部署方法

1.1 Docker简介

Docker之父Solomon HykesDocker就好比传统的货运集装箱
Note
2008 LXC(LinuX Contiainer)发布,但是没有行业标准,兼容性非常差
docker2013年首次发布,由Docker, Inc开发

1.1.1 什么是docker

Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术
它具有以下几个重要特点和优势:
1. 轻量级虚拟化
Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。
        例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。
2. 一致性
:确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。
        无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。
3. 可移植性
:可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差
异。
        比如,在本地开发的容器可以无缝部署到云服务器上。
4. 高效的资源利用:多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资
源。
5. 易于部署和扩展:能够快速部署新的应用实例,并且可以根据需求轻松地进行水平扩展。
总之,Docker 极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。
它在现代软件开发和云计算领域得到了广泛的应用。

1.1.2 docker在企业中的应用场景

在企业中docker作为业务的最小载体而被广泛应用
通过docker企业可以更效率的部署应用并更节省资源
Note
IaaSInfrastructure as a Service),即基础设施即服务
PaaS是(Platform as a Service)即指平台即服务
SaaSSoftware as a Service)软件运营服务是

1.1.3 docker与虚拟化的对比

1.1.4 docker的优势

  • 对于开发人员:Build onceRun anywhere
  • 对于运维人员:Configure onceRun anything
  • 容器技术大大提升了IT人员的幸福指数!

2 部署docker

2.1 容器工作方法

2.2 部署第一个容器

官方站点:https://docs.docker.com/

2.3 安装docker-ce

2.2.1 配置软件仓库

vim /etc/yum.repos.d/docker.repo

编辑如下内容: 

[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable
gpgcheck=0

卸载podman:

查询podman包

rpm -qa | grep podman

进行卸载: 

dnf remove podman-4.2.0-3.el9.x86_64 -y

再次查询,确认卸载干净:

rpm -qa | grep podman

卸载冲突包:

sudo dnf remove -y buildah runc

2.2.2 安装docker-ce并启动服务

yum install -y docker-ce

#编辑docker启动文件,设定其使用iptables的网络设定方式,默认使用nftables

vim /lib/systemd/system/docker.service 
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 
--iptables=true

2.2.3 激活内核网络选项

echo net.ipv4.ip_forward = 1 > /etc/sysctl.d/docker.conf

刷新系统内核参数和重启 Docker 服务:

sysctl --system 
systemctl restart docker

(注意)

#在rhel7中 需要
]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
]# sysctl --system
]# systemctl restart docker

3 Docker的基本操作

3.1 Docker镜像管理:

3.1.1  镜像搜索:

docker search nginx

查看本地镜像:

docker images
[root@docker packages]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        1.23      a7be6198544f   2 years ago   142MB

3.1.2 拉取镜像:

[root@Docker-node1 ~]# docker pull busybox
[root@Docker-node1 ~]# docker pull nginx:1.26-alpine


3.1.3 查看镜像信息:

docker image inspect nginx:1.23
[root@docker packages]# docker image inspect nginx:1.23 
[{"Id": "sha256:a7be6198544f09a75b26e6376459b47c5b9972e7aa742af9f356b540fe852cd4","RepoTags": ["nginx:1.23"],"RepoDigests": [],"Parent": "","Comment": "","Created": "2023-05-23T08:51:38.011802405Z","DockerVersion": "20.10.23","Author": "","Architecture": "amd64","Os": "linux","Size": 142145851,"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/e96e76939958426de535ea7d668c10ea0910a2bdafea9776271c0e2d37cf685c/diff:/var/lib/docker/overlay2/b716465abcc0d148b864758dff55bcc4c1ecaa7dab111ea8cedd12986cffdd3c/diff:/var/lib/docker/overlay2/d61e1a60886964ff9f407a0640b16941a0dddb80eb16446a73026364b5eafec9/diff:/var/lib/docker/overlay2/e89fafbf7412f392423c0d014ae9a9d7190ef256420db94746235c442cf466a2/diff:/var/lib/docker/overlay2/1a713b6c5dc96eef002a165325a805bde3b7de0cd00845b43b64b5b8aa90d8cf/diff","MergedDir": "/var/lib/docker/overlay2/181001765be769571578488be650304e134037bb0d4e5364fdd39facc541d91e/merged","UpperDir": "/var/lib/docker/overlay2/181001765be769571578488be650304e134037bb0d4e5364fdd39facc541d91e/diff","WorkDir": "/var/lib/docker/overlay2/181001765be769571578488be650304e134037bb0d4e5364fdd39facc541d91e/work"},"Name": "overlay2"},"RootFS": {"Type": "layers","Layers": ["sha256:8cbe4b54fa88d8fc0198ea0cc3a5432aea41573e6a0ee26eca8c79f9fbfa40e3","sha256:5dd6bfd241b4f4d0bb0a784cd7cefe00829edce2fccb2fcad71244df6344abff","sha256:043198f57be0cb6dd81abe9dd01531faa8dd2879239dc3b798870c0604e1bb3c","sha256:2731b5cfb6163ee5f1fe6126edb946ef11660de5a949404cc76207bf8a9c0e6e","sha256:6791458b394218a2c05b055f952309afa42ec238b74d5165cf1e2ebe9ffe6a33","sha256:4d33db9fdf22934a1c6007dcfbf84184739d590324c998520553d7559a172cfb"]},"Metadata": {"LastTagTime": "0001-01-01T00:00:00Z"},"Config": {"Cmd": ["nginx","-g","daemon off;"],"Entrypoint": ["/docker-entrypoint.sh"],"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","NGINX_VERSION=1.23.4","NJS_VERSION=0.7.11","PKG_RELEASE=1~bullseye"],"ExposedPorts": {"80/tcp": {}},"Labels": {"maintainer": "NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e"},"OnBuild": null,"StopSignal": "SIGQUIT","User": "","Volumes": null,"WorkingDir": ""}}
]

3.1.4 导入镜像:

docker load -i game2048.tar.gz
[root@docker packages]# docker load -i game2048.tar.gz 
011b303988d2: Loading layer [==================================================>]   5.05MB/5.05MB
36e9226e74f8: Loading layer [==================================================>]  51.46MB/51.46MB
192e9fad2abc: Loading layer [==================================================>]  3.584kB/3.584kB
6d7504772167: Loading layer [==================================================>]  4.608kB/4.608kB
88fca8ae768a: Loading layer [==================================================>]  629.8kB/629.8kB
Loaded image: timinglee/game2048:latest

3.1.5 导出镜像:

镜像保存,

docker image save  名字 : 版本  -o 输出路径

docker image save   nginx:1.23 -o test-nginx.tar.gz

保存导出多个镜像:
docker image save  名字 : 版本  名字 : 版本  -o 输出路径

docker image save   nginx:1.23 timinglee/game2048:latest -o test-nginx-2048.tar.gz

保存所有镜像:

docker save  `docker images | awk 'NR>1{print $1":"$2}'` -o images.tar.gz

3.1.6 删除镜像:

docker rmi nginx:1.23
[root@docker packages]# docker rmi nginx:1.23 
Untagged: nginx:1.23
Deleted: sha256:a7be6198544f09a75b26e6376459b47c5b9972e7aa742af9f356b540fe852cd4
Deleted: sha256:b142903ff5d25e779c293678ce1bb71604778bc243cda8c26180675454fbf11c
Deleted: sha256:185fa8597cdc03f83ab9ec3fe21d8ac6fbe49fa65cf8422f05d1d07b06b25fce
Deleted: sha256:1e3de4dfc3a245258917d9cd0860bd30969e1b430ecba95b1eaf2666d8882d24
Deleted: sha256:95b14e2b8329c1fcec4e1df001aac4874bc2247281ae96cdfe355847faf4caa9
Deleted: sha256:8566a5cb57a5d27b0eba5d952429bc542c05853014dc2c8f362540e7533fbff9
Deleted: sha256:8cbe4b54fa88d8fc0198ea0cc3a5432aea41573e6a0ee26eca8c79f9fbfa40e3

删除全部镜像:

 docker rmi  `docker images | awk 'NR>1{print $1":"$2}'`

3.2 容器的常用操作

3.2.1 启动容器:

docker run -d --name game2048 -p 80:80 timinglee/game2048

查看进程:

docker ps

访问容器映射页面:

172.25.254.10:80

-d #后台运行
-i #交互式运行
-t #打开一个终端
--name #指定容器名称
-p #端口映射 -p 808080 把容器8080端口映射到本机80端口
--rm #容器停止自动删除容器
--network #指定容器使用的网络

3.2.2 查看容器运行信息

[root@Docker-node1 ~]# docker ps #查看当前运行容器
[root@Docker-node1 ~]# docker ps -a #查看所有容器
[root@Docker-node1 ~]# docker inspect busybox #查看容器运行的详细信息

3.2.3 停止和运行容器

[root@Docker-node1 ~]# docker stop busybox #停止容器
[root@Docker-node1 ~]# docker kill busybox #杀死容器,可以使用信号
[root@Docker-node1 ~]# docker start busybox #开启停止的容器
容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!

3.2.4 删除容器

[root@Docker-node1 ~]# docker rm centos7 #删除停止的容器
[root@Docker-node1 ~]# docker rm -f busybox #删除运行的容器
[root@Docker-node1 ~]# docker container prune -f #删除所有停止的容器

3.2.5 容器内容提交
默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件
如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像
当我们在运行新镜像后即可看到我们提交的内容

[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 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:c8ff62b7480c951635acb6064acdfeb25282bd0c19cbffee0e51f3902cbfa4bd
[root@Docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
busybox v1 c8ff62b7480c 12 seconds ago
4.26MB
[root@Docker-node1 ~]# docker image history busybox:v1
IMAGE CREATED CREATED BY SIZE
COMMENT
c8ff62b7480c 2 minutes ago sh 17B add
leefile
65ad0d468eb1 15 months ago BusyBox 1.36.1 (glibc), Debian 12 4.26MB
此方法不利于企业审计,所以不推荐使用,在企业中我们多用Dockerfile来构建镜像

3.2.6 系统中的文件和容器中的文件传输

[root@Docker-node1 ~]# docker cp test2:/leefile /mnt #把容器中的文件复制到本机
Successfully copied 1.54kB to /mnt
[root@Docker-node1 ~]# docker cp /etc/fstab test2:/fstab #把本机文件复制到容器中

3.2.7 查询容器内部日志

[root@Docker-node1 ~]# docker logs web
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to
perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-bydefault.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of
/etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in
/etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/08/14 07:50:01 [notice] 1#1: using the "epoll" event method
2024/08/14 07:50:01 [notice] 1#1: nginx/1.27.0
2024/08/14 07:50:01 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14)
2024/08/14 07:50:01 [notice] 1#1: OS: Linux 5.14.0-427.13.1.el9_4.x86_64
2024/08/14 07:50:01 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1073741816:1073741816
2024/08/14 07:50:01 [notice] 1#1: start worker processes
2024/08/14 07:50:01 [notice] 1#1: start worker process 29
2024/08/14 07:50:01 [notice] 1#1: start worker process 30
172.17.0.1 - - [14/Aug/2024:07:50:20 +0000] "GET / HTTP/1.1" 200 615 "-"
"curl/7.76.1" "-"

4 镜像构建

4.1 docker镜像结构

  • 共享宿主机的kernel
  • base镜像提供的是最小的Linux发行版
  • 同一docker主机支持运行多种Linux发行版
  • 采用分层结构的最大好处是:共享资源

4.2 镜像运行的基本原理

  • Copy-on-Write 可写容器层
  • 容器层以下所有镜像层都是只读的
  • docker从上往下依次查找文件
  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
  • 一个镜像最多127

4.3 镜像获得方式

  • 基本镜像通常由软件官方提供
  • 企业镜像可以用官方镜像+Dockerfile来生成
  • 系统关于镜像的获取动作有两种:
    • docker pull 镜像地址
    • docker load –i 本地镜像包

4.4 镜像构建

4.4.1 构建参数

FROM指定base镜像 eg:FROM busybox:version
COPY复制文件 eg:COPY file /file 或者 COPY [“file”,”/”]
MAINTAINER指定作者信息,比如邮箱 eg:MAINTAINER user@example.com 在最新版的docker中用LABEL KEY="VALUE"代替
ADD功能和copy相似,指定压缩文件或url eg: ADD test.tar /mnt 或者 eg:ADD http://ip/test.tar /mnt
ENV指定环境变量 eg:ENV FILENAME test
EXPOSE暴漏容器端口 eg:EXPOSE 80
VOLUME申明数据卷,通常指数据挂载点 eg:VOLUME [“/var/www/html”]
WORKDIR切换路径 eg:WORKDIR /mnt
RUN在容器中运行的指令 eg: touch file
CMD在启动容器时自动运行动作可以被覆盖 eg:CMD echo $FILENAME 会调用shell解析 eg:CMD [“/bin/sh”,”-c”,“echo $FILENAME”] 不调用shell解析
ENTRYPOINT和CMD功能和用法类似,但动作不可被覆盖

参数示例及用法

FROM COPY 和MAINTAINER

导入要构建的镜像:

docker load -i busybox-latest.tar.gz
[root@docker packages]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED       SIZE
busybox              latest    65ad0d468eb1   2 years ago   4.26MB
timinglee/game2048   latest    19299002fdbe   8 years ago   55.5MB

创建构建文件夹:

mkdir ~/docker
cd ~/docker/

编辑构建文件:

touch rin_file
vim rin_file
FROM busybox:latest            #指定使用的基础镜像
MAINTAINER rin@rin.com         #指定作者信息
COPY rin_file /	               #复制当前目录文件到容器指定位置,leefile必须在当前目录中

构建镜像:

docker build -t example:v1  -f rin_file .

查看构建情况:

[root@docker docker]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
example              v1        0f34c76c5f1c   9 minutes ago   4.26MB
busybox              latest    65ad0d468eb1   2 years ago     4.26MB
timinglee/game2048   latest    19299002fdbe   8 years ago     55.5MB

运行容器查看动作是否执行:

docker run -it --rm example:v1 sh
[root@docker docker]# docker run -it --rm example:v1 sh
/ # ls
bin       etc       lib       proc      root      tmp       var
dev       home      lib64     rin_file  sys       usr
/ # cat rin_file 
FROM busybox:latest
MAINTAINER rin@rin.com
COPY rin_file /	/ # exit

4.1.2 镜像构建实例:

当前contos7的软件仓库不可用,重新构建一个软件仓库能用contos7镜像:

将原本的镜像挂载:

docker load -i centos-7.tar.gz

创建构建文件夹,并切换路径:

mkdir /docker/contos7-test
cd /docker/contos7-test

编辑要更换的repo文件:

vim rhel7.repo 
[base]
name = rhel7
baseurl = https://mirrors.aliyun.com/centos/7/os/x86_64/
gpgcheck = 0

编辑Dockerfile 文件:

vim Dockerfile 
FROM centos:7
RUN rm -f /etc/yum.repos.d/*.repo
COPY rhel7.repo /etc/yum.repos.d/

重新构建软件仓库能用的conntos7镜像:

docker build -t centos7-repo:v1 .

测试:

进入实例测试,

docker run -it --rm centos7-repo:v1 bash
[root@f30a4e3588a0 /]# yum install gcc  
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
base                                                                                                 | 3.6 kB  00:00:00     
(1/2): base/group_gz                                                                                 | 153 kB  00:00:06     
(2/2): base/primary_db                                                                               | 6.1 MB  00:00:11     
Resolving Dependencies
--> Running transaction check
---> Package gcc.x86_64 0:4.8.5-44.el7 will be installed
--> Processing Dependency: libgomp = 4.8.5-44.el7 for package: gcc-4.8.5-44.el7.x86_64
--> Processing Dependency: cpp = 4.8.5-44.el7 for package: gcc-4.8.5-44.el7.x86_64
--> Processing Dependency: glibc-devel >= 2.2.90-12 for package: gcc-4.8.5-44.el7.x86_64
--> Processing Dependency: libmpfr.so.4()(64bit) for package: gcc-4.8.5-44.el7.x86_64
--> Processing Dependency: libmpc.so.3()(64bit) for package: gcc-4.8.5-44.el7.x86_64
--> Processing Dependency: libgomp.so.1()(64bit) for package: gcc-4.8.5-44.el7.x86_64
--> Running transaction check
---> Package cpp.x86_64 0:4.8.5-44.el7 will be installed
---> Package glibc-devel.x86_64 0:2.17-317.el7 will be installed
--> Processing Dependency: glibc-headers = 2.17-317.el7 for package: glibc-devel-2.17-317.el7.x86_64
--> Processing Dependency: glibc-headers for package: glibc-devel-2.17-317.el7.x86_64
---> Package libgomp.x86_64 0:4.8.5-44.el7 will be installed
---> Package libmpc.x86_64 0:1.0.1-3.el7 will be installed
---> Package mpfr.x86_64 0:3.1.1-4.el7 will be installed
--> Running transaction check
---> Package glibc-headers.x86_64 0:2.17-317.el7 will be installed
--> Processing Dependency: kernel-headers >= 2.2.1 for package: glibc-headers-2.17-317.el7.x86_64
--> Processing Dependency: kernel-headers for package: glibc-headers-2.17-317.el7.x86_64
--> Running transaction check
---> Package kernel-headers.x86_64 0:3.10.0-1160.el7 will be installed
--> Finished Dependency ResolutionDependencies Resolved============================================================================================================================Package                          Arch                     Version                             Repository              Size
============================================================================================================================
Installing:gcc                              x86_64                   4.8.5-44.el7                        base                    16 M
Installing for dependencies:cpp                              x86_64                   4.8.5-44.el7                        base                   5.9 Mglibc-devel                      x86_64                   2.17-317.el7                        base                   1.1 Mglibc-headers                    x86_64                   2.17-317.el7                        base                   690 kkernel-headers                   x86_64                   3.10.0-1160.el7                     base                   9.0 Mlibgomp                          x86_64                   4.8.5-44.el7                        base                   159 klibmpc                           x86_64                   1.0.1-3.el7                         base                    51 kmpfr                             x86_64                   3.1.1-4.el7                         base                   203 kTransaction Summary
============================================================================================================================
Install  1 Package (+7 Dependent packages)Total download size: 33 M
Installed size: 60 M
Is this ok [y/d/N]: n


 

4.5 镜像优化:

3.5.1 镜像优化策略
  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物
  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物

4.5.2 镜像优化示例

方法1.缩减镜像层
[root@server1 docker]# vim Dockerfile
FROM centos:7 as build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS
-g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --
with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-
1.23.3 && yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t webserver:v2 .
[root@server1 docker]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v2 caf0f80f2332 4 seconds ago 317MB
webserver v1 bfd6774cc216 About an hour ago 494MB
方法2.多阶段构建
[root@server1 docker]# vim Dockerfile
FROM centos:7 as build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS
-g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --
with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-
1.23.3 && yum clean all
FROM centos:7
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@server1 docker]# docker build -t webserver:v3 .
[root@server1 docker]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v3 1ac964f2cefe 29 seconds ago 205MB
webserver v2 caf0f80f2332 3 minutes ago 317MB
webserver v1 bfd6774cc216 About an hour ago 494MB
方法3.使用最精简镜像
使用google提供的最精简镜像
下载地址:
https://github.com/GoogleContainerTools/distroless
下载镜像:
docker pull gcr.io/distroless/base
利用最精简镜像构建
[root@server1 ~]# mkdir new
[root@server1 ~]# cd new/
[root@server1 new]# vim Dockerfile
FROM nginx:latest 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@server1 new]# docker build -t webserver:v4 .
[root@server1 new]# docker images webserver
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v4 c0c4e1d49f3d 4 seconds ago 34MB
webserver v3 1ac964f2cefe 12 minutes ago 205MB
webserver v2 caf0f80f2332 15 minutes ago 317MB
webserver v1 bfd6774cc216 About an hour ago 494MB

5 Docker 镜像仓库的管理

5.1什么是docker仓库

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

5.2 docker hub

官网:https://hub.docker.com/

Docker Hub Docker 官方提供的一个公共的镜像仓库服务。
它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,拥有大量的官方和社区贡献的镜像。
以下是 Docker Hub 的一些关键特点和优势:
1. 丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用
的镜像。
  • 例如,您可以轻松找到 UbuntuCentOS 等操作系统的镜像,以及 MySQLRedis 等数据库 的镜像。
2. 官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。
3. 社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。
4. 版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。
5. 便于搜索:用户可以通过关键词轻松搜索到所需的镜像。

5.2.1 docker hub的使用方法

#登陆官方仓库
[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 gcr.io/distroless/base-debian11:latest
timinglee/base-debian11:latest
[root@docker ~]# docker push timinglee/base-debian11:latest
The push refers to repository [docker.io/timinglee/base-debian11]
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:f8179c20f1f2b1168665003412197549bd4faab5ccc1b140c666f9b8aa958042 size:
3234

5.3 docker仓库的工作原理

仓库中的三个角色
index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index
Auth serviceToken的方式进行认证
Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。

5.3.1pull原理

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

5.3.2 push原理

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

5.4 搭建docker的私有仓库

5.4.1 为什么搭建私有仓库

docker hub虽然方便,但是还是有限制
  • 需要internet连接,速度慢
  • 所有人都可以访问
  • 由于安全原因企业不允许将镜像放到外网
好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库
地址: https://docs.docker.com/registry/deploying/

5.4.2 搭建简单的Registry仓库

下载Registry镜像

docker load -i registry.tag.gz

开启Registry
docker run -d -p 5000:5000 --restart=always --name registry registry:latest

查看进程:

[root@docker packages]# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                                         NAMES
3cb75b901caa   registry:latest   "/entrypoint.sh /etc…"   39 seconds ago   Up 38 seconds   0.0.0.0:5000->5000/tcp, [::]:5000->5000/tcp   registry

5.4.3上传镜像到仓库:

5.4.3.1免密上传:
#配置非加密端口
vim /etc/docker/daemon.json
{
"insecure-registries" : ["http://172.25.254.10:5000"]
}

重启docker:
 

systemctl restart docker

上传镜像:
给要传的镜像打标签:

docker tag busybox:latest 172.25.254.10:5000/busybox:latest

上传:

docker push 172.25.254.10:5000/busybox:latest

查看上传好的镜像:

[root@docker packages]# curl 172.25.254.10:5000/v2/_catalog
{"repositories":["busybox"]}

测试:

将镜像目录的busybox删除:

docker rmi busybox:latest
[root@docker packages]# docker images
REPOSITORY                    TAG       IMAGE ID       CREATED          SIZE
centos7-repo                  v1        82409bfb1c95   43 minutes ago   204MB
example                       v1        0f34c76c5f1c   43 hours ago     4.26MB
registry                      latest    cfb4d9904335   22 months ago    25.4MB
nginx                         1.23      a7be6198544f   2 years ago      142MB
172.25.254.100:5000/busybox   latest    65ad0d468eb1   2 years ago      4.26MB
172.25.254.10:5000/busybox    latest    65ad0d468eb1   2 years ago      4.26MB
centos                        7         eeb6ee3f44bd   3 years ago      204MB
timinglee/game2048            latest    19299002fdbe   8 years ago      55.5MB

再从本地仓库拉取:
 

docker pull 172.25.254.10:5000/busybox:latest
[root@docker packages]# docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
centos7-repo                 v1        82409bfb1c95   46 minutes ago   204MB
example                      v1        0f34c76c5f1c   43 hours ago     4.26MB
registry                     latest    cfb4d9904335   22 months ago    25.4MB
nginx                        1.23      a7be6198544f   2 years ago      142MB
172.25.254.10:5000/busybox   latest    65ad0d468eb1   2 years ago      4.26MB
centos                       7         eeb6ee3f44bd   3 years ago      204MB
timinglee/game2048           latest    19299002fdbe   8 years ago      55.5MB

5.4.3.2 加密传输:

创建证书存放文件夹:

mkdir -p /root/certs
cd /root
openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout certs/rin.key \
-addext "subjectAltName = DNS:www.rin.com" \
-x509 -days 365 -out certs/rin.crt

Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:guangxi
Locality Name (eg, city) [Default City]:nanning
Organization Name (eg, company) [Default Company Ltd]:rin
Organizational Unit Name (eg, section) []:docker
Common Name (eg, your name or your server's hostname) []:www.rin.com                                                                                              #其余随意填,这条得填跟上面dns一样的内容
Email Address []:rin@rin.com

#启动registry仓库
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/rin.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/rin.key registry

将证书复制到 Docker 的证书信任目录中

# 1. 创建证书目录(注意替换为你的域名 www.rin.com) 
sudo mkdir -p /etc/docker/certs.d/www.rin.com # 2. 将证书复制到该目录(假设证书在当前主机的 /root/certs/rin.crt) 
cp /root/certs/rin.crt /etc/docker/certs.d/www.rin.com/ca.crt # 3. 重启 Docker 服务使配置生效 
sudo systemctl restart docker

# 为busybox镜像添加标签,并推送:

​​​​​​​# 为busybox镜像添加标签(假设你要推送的是busybox这个镜像) 
docker tag busybox:latest www.rin.com/busybox:latest # 进行推送了 
docker push www.rin.com/busybox:latest

查看推送情况:
 

[root@docker ~]# curl -k https://www.rin.com/v2/_catalog
{"repositories":["busybox"]}

5.4.4 为仓库建立登陆认证

#安装建立认证文件的工具包
dnf install httpd-tools -y
#建立认证文件
mkdir auth
#-B 强制使用最安全加密方式,默认用md5加密
htpasswd -Bc auth/htpasswd rin
[root@docker ~]# htpasswd -Bc /root/auth/htpasswd rin
New password: 
Re-type new password: 
Adding password for user rin
#添加认证到registry容器中
 docker run -d -p 443:443 
--restart=always 
--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/rin.crt 
-e REGISTRY_HTTP_TLS_KEY=/certs/rin.key 
-v /root/auth:/auth 
-e "REGISTRY_AUTH=htpasswd" 
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" 
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry

测试:
 

[root@docker ~]# curl -k https://www.rin.com/v2/_catalog -u rin:123
{"repositories":["busybox"]}

登入测试:

docker login www.rin.com
[root@docker ~]# docker login www.rin.com
Username: rin
Password: WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/Login Succeeded

5.5 构建企业级私有仓库

下载软件包地址
https://github.com/goharbor/harbor/releases
Harbor 是由vmware公司开源的企业级 Docker Registry 项目。
它提供了以下主要功能和特点:
  1. 基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理的灵活性。
  2. 镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。
  3. 图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。
  4. 审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
  5.  垃圾回收:可以清理不再使用的镜像,节省存储空间。

5.5.1 部署harbor

tar xzf harbor-offline-installer-v2.5.4.tgz

创建证书存放文件夹:

mkdir -p /data/certs
cd /data
openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout certs/rin.key \
-addext "subjectAltName = DNS:www.rin.com" \
-x509 -days 365 -out certs/rin.crt

Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:guangxi
Locality Name (eg, city) [Default City]:nanning
Organization Name (eg, company) [Default Company Ltd]:rin
Organizational Unit Name (eg, section) []:docker
Common Name (eg, your name or your server's hostname) []:www.rin.com                                                                                              #其余随意填,这条得填跟上面dns一样的内容
Email Address []:rin@rin.com

编辑文件:
 

cd harbor/
cp harbor.yml.tmpl harbor.yml
vim harbor.yml
# Configuration file of Harbor# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: www.rin.com# https related config
https:# https port for harbor, default is 443port: 443# The path of cert and key files for nginxcertificate: /data/certs/rin.crtprivate_key: /data/certs/rin.key# The initial password of Harbor admin
# It only works in first time to install harbor
# Remember Change the admin password from UI after launching Harbor.
harbor_admin_password: rin# The default data volume
data_volume: /data

执行安装脚本:

执行前记得将同名镜像容器删除:
 

docker rm -f registry
./install.sh --with-chartmuseum

#管理harbor的容器
docker compose stop 
docker compose up -d
[root@docker harbor]# docker compose stop
WARN[0000] /mnt/packages/harbor/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Stopping 10/10✔ Container harbor-jobservice  Stopped                                                                                0.6s ✔ Container registryctl        Stopped                                                                               10.2s ✔ Container chartmuseum        Stopped                                                                                0.6s ✔ Container nginx              Stopped                                                                                0.5s ✔ Container harbor-portal      Stopped                                                                                0.3s ✔ Container harbor-core        Stopped                                                                                3.3s ✔ Container registry           Stopped                                                                                0.2s ✔ Container redis              Stopped                                                                                0.5s ✔ Container harbor-db          Stopped                                                                                0.3s ✔ Container harbor-log         Stopped                                                                               10.3s 
[root@docker harbor]# docker compose up -d
WARN[0000] /mnt/packages/harbor/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Running 10/10✔ Container harbor-log         Started                                                                                0.5s ✔ Container harbor-portal      Started                                                                                2.6s ✔ Container harbor-db          Started                                                                                1.1s ✔ Container redis              Started                                                                                2.8s ✔ Container registry           Started                                                                                2.8s ✔ Container chartmuseum        Started                                                                                2.7s ✔ Container registryctl        Started                                                                                2.7s ✔ Container harbor-core        Started                                                                                1.0s ✔ Container nginx              Started                                                                                1.3s ✔ Container harbor-jobservice  Started                                                                                0.7s 

5.5.2 管理仓库

登录私有仓库:

建立仓库项目:

上传镜像:

[root@docker harbor]# docker push www.rin.com/rinfile/example:v1 
The push refers to repository [www.rin.com/rinfile/example]
bcbeb1265327: Pushed 
d51af96cf93e: Pushed 
v1: digest: sha256:64743a2cdb84b0a21e7132de9bdc8d592cc3b90a035b93c05cf6941620b43d27 size: 734


 

添加标签:
docker tag 本地镜像 仓库地址/项目名/镜像名:标签

docker tag example:v1 www.rin.com/rinfile/example:v1

上传镜像:

docker push www.rin.com/rinfile/example:v1
[root@docker harbor]# docker push www.rin.com/rinfile/example:v1 
The push refers to repository [www.rin.com/rinfile/example]
bcbeb1265327: Pushed 
d51af96cf93e: Pushed 
v1: digest: sha256:64743a2cdb84b0a21e7132de9bdc8d592cc3b90a035b93c05cf6941620b43d27 size: 734

查看上传的镜像:

Docker 网络

docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分
docker安装后会自动创建3种网络:bridgehostnone
[root@docker harbor]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2a93d6859680 bridge bridge local
4d81ddd9ed10 host host local
8c8c95f16b68 none null local

6.1 docker原生bridge网路

docker安装时会创建一个名为 docker0 Linux bridge,新建的容器会自动桥接到这个接口
[root@docker mnt]# 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:5f:e2:34:6c brd ff:ff:ff:ff:ff:ff
  • bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。
  • 容器通过宿主机的NAT规则后可以访问外网

[root@docker mnt]# docker run -d --name web -p 80:80 nginx:1.23
defeba839af1b95bac2a200fd1e06a45e55416be19c7e9ce7e0c8daafa7dd470
[root@docker mnt]# 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:5fff:fee2:346c prefixlen 64 scopeid 0x20<link>
ether 02:42:5f:e2:34:6c txqueuelen 0 (Ethernet)
RX packets 21264 bytes 1497364 (1.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27358 bytes 215202237 (205.2 MiB)
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::30b2:327e:b13a:31cf prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:ec:fc:d3 txqueuelen 1000 (Ethernet)
RX packets 1867778 bytes 2163432019 (2.0 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 822980 bytes 848551940 (809.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 11819 bytes 1279944 (1.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 11819 bytes 1279944 (1.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth022a7c9: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::a013:5fff:fefc:c9e4 prefixlen 64 scopeid 0x20<link>
ether a2:13:5f:fc:c9:e4 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 15 bytes 2007 (1.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth022a7c9 为容器使用的网卡
[root@docker mnt]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02425fe2346c no veth022a7c9

6.2 docker原生网络host

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

[root@docker ~]# docker run -it --name test --network host busybox
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:5F:E2:34:6C
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:5fff:fee2:346c/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:21264 errors:0 dropped:0 overruns:0 frame:0
TX packets:27359 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1497364 (1.4 MiB) TX bytes:215202367 (205.2 MiB)
eth0 Link encap:Ethernet HWaddr 00:0C:29:EC:FC:D3
inet addr:172.25.254.100 Bcast:172.25.254.255 Mask:255.255.255.0
inet6 addr: fe80::30b2:327e:b13a:31cf/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1902507 errors:0 dropped:0 overruns:0 frame:0
TX packets:831640 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2202443300 (2.0 GiB) TX bytes:849412124 (810.0 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:11819 errors:0 dropped:0 overruns:0 frame:0
TX packets:11819 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1279944 (1.2 MiB) TX bytes:1279944 (1.2 MiB)
如果公用一个网络,那么所有的网络资源都是公用的,比如启动了nginx容器那么真实主机的80端口被占用,在启动第二个nginx容器就会失败

6.3 docker 原生网络none

none模式是指禁用网络功能,只有lo接口,在容器创建时使用
--network=none指定。
[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)

6.4 docker的自定义网络

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

6.4.1 自定义桥接网络

在建立自定以网络时,默认使用桥接模式
[root@docker ~]# docker network create my_net1
f2aae5ce8ce43e8d1ca80c2324d38483c2512d9fb17b6ba60d05561d6093f4c4
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2a93d6859680 bridge bridge local
4d81ddd9ed10 host host local
f2aae5ce8ce4 my_net1 bridge local
8c8c95f16b68 none null local
桥接默认是单调递增
[root@docker ~]# ifconfig
br-f2aae5ce8ce4: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:70:57:f2:82 txqueuelen 0 (Ethernet)
RX packets 21264 bytes 1497364 (1.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27359 bytes 215202367 (205.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:5fff:fee2:346c prefixlen 64 scopeid 0x20<link>
ether 02:42:5f:e2:34:6c txqueuelen 0 (Ethernet)
RX packets 21264 bytes 1497364 (1.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27359 bytes 215202367 (205.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
桥接也支持自定义子网和网关
[root@docker ~]# docker network create my_net2 --subnet 192.168.0.0/24 --gateway
192.168.0.100
7e77cd2e44c64ff3121a1f1e0395849453f8d524d24b915672da265615e0e4f9
[root@docker ~]# docker network inspect my_net2
[{"Name": "my_net2","Id": "7e77cd2e44c64ff3121a1f1e0395849453f8d524d24b915672da265615e0e4f9","Created": "2024-08-17T17:05:19.167808342+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": {}}
]

6.4.2 为什么要自定义桥接

多容器之间如何互访?通过ip可以,但是有什么问题?
[root@docker ~]# docker inspect web1
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null,
"NetworkID":
"2a93d6859680b45eae97e5f6232c3b8e070b1ec3d01852b147d2e1385034bce5",
"EndpointID":
"4d54b12aeb2d857a6e025ee220741cbb3ef1022848d58057b2aab544bd3a4685",
"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":
"2a93d6859680b45eae97e5f6232c3b8e070b1ec3d01852b147d2e1385034bce5",
"EndpointID":
"4d54b12aeb2d857a6e025ee220741cbb3ef1022848d58057b2aab544bd3a4685",
"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 web nginx
d9ed01850f7aae35eb1ca3e2c73ff2f83d13c255d4f68416a39949ebb8ec699f
[root@docker ~]# docker run -it --network my_net1 --name test busybox
/ # ping web
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可以看到网络隔离策略

6.4.3 如何让不同的自定义网络互通?

[root@docker ~]# docker run -d --name web1 --network my_net1 nginx
[root@docker ~]# docker run -it --name test --network my_net2 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:00:01
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.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 172.18.0.2
PING 172.18.0.2 (172.18.0.2): 56 data bytes
[root@docker ~]# docker network connect my_net1 test
#在上面test容器中加入网络eth1
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:00:01
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:45 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:5879 (5.7 KiB) TX bytes:602 (602.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:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:212 (212.0 B) TX bytes:212 (212.0 B)

6.4.4 joined网络示例演示

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

创建名为 my_net1 的网络:

docker network create my_net1

将phpmyadmin和mysq镜像进行加载:

 docker load -i phpmyadmin-latest.tar.gz docker load -i mysql-5.7.tar.gz 
#运行phpmysqladmin
docker run -d --name mysqladmin --network my_net1 
-e PMA_ARBITRARY=1                 #在web页面中可以手动输入数据库地址和端口
-p 80:80 phpmyadmin:latest
#运行数据库
docker run -d --name mysql 
-e MYSQL_ROOT_PASSWORD='rin'              #设定数据库密码
--network container:mysqladmin            #把数据库容器添加到phpmyadmin容器中
mysql:5.7

在页面进行访问:

6.5 容器内外网的访问

6.5.1 容器访问外网

  • rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网
  • rhel7之后的版本中通过nftables添加地址伪装来访问外网
[root@docker ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE 6 -- 172.17.0.2 172.17.0.2 tcp dpt:80 #
内网访问外网策略
Chain DOCKER (0 references)
target prot opt source destination
DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
to:172.17.0.2:80

6.5.2 外网访问docker容器

端口映射 -p 本机端口:容器端口来暴漏端口从而达到访问效果
#通过docker-proxy对数据包进行内转
[root@docker ~]# docker run -d --name webserver -p 80:80 nginx
[root@docker ~]# ps ax
133986 ? 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
133995 ? Sl 0:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -hostport 80 -container-ip 172.17.0.2 -container-port 80
134031 ? Sl 0:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id
cae79497a01c0b8c488c7597b43de4a43f361f21a398ff423b4504c0905db143 -address
/run/containerd/containerd.sock
134059 ? Ss 0:00 nginx: master process nginx -g daemon off;
134099 ? S 0:00 nginx: worker process
134100 ? S 0:00 nginx: worker process
#通过dnat策略来完成浏览内转
[root@docker ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE 6 -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (0 references)
target prot opt source destination
DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
to:172.17.0.2:80
docker-proxydnat在容器建立端口映射后都会开启,那个传输速录高走那个

6.6 docker跨主机网络

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

6.6.1 CNM Container Network Model

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

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

macvlan网络方式
  • Linux kernel提供的一种网卡虚拟化技术。
  • 无需Linux bridge,直接使用物理接口,性能极好
  • 容器的接口直接与主机网卡连接,无需NAT或端口映射。macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
  • vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094
macvlan网络间的隔离和连通
  • macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的
  • 可以在三层上通过网关将macvlan网络连通起来
  • docker本身不做任何限制,像传统vlan网络那样管理即可
添加一块新网卡:
在两台docker主机上各添加一块网卡,打开网卡混杂模式:
ip link set eth1 promisc on
ip link set up eth1
ifconfig eth1

添加macvlan网路

 docker network create  
-d macvlan 
--subnet 1.1.1.0/24 
--gateway 1.1.1.1 
-o parent=eth1 macvlan1 

挂载镜像:

docker load -i busybox-latest.tar.gz 

测试:
主机1:

docker run -it --name busybox --network macvlan1 --ip 1.1.1.100 --rm busybox

主机2:

docker run -it --name busybox --network macvlan1 --ip 1.1.1.200 --rm busybox

[root@docker packages]# docker run -it --name busybox --network macvlan1 --ip 1.1.1.100 --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
13: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 66:6e:ba:48:ba:cc brd ff:ff:ff:ff:ff:ffinet 1.1.1.100/24 brd 1.1.1.255 scope global eth0valid_lft forever preferred_lft forever
/ # ping 1.1.1.200
PING 1.1.1.200 (1.1.1.200): 56 data bytes
64 bytes from 1.1.1.200: seq=0 ttl=64 time=1.086 ms
64 bytes from 1.1.1.200: seq=1 ttl=64 time=0.841 ms
^C
--- 1.1.1.200 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.841/0.963/1.086 ms

7 Docker 数据卷管理及优化

Docker 数据卷是一个可供容器使用的特殊目录,它绕过了容器的文件系统,直接将数据存储在宿主机
上。
这样可以实现以下几个重要的目的:
  • 数据持久化:即使容器被删除或重新创建,数据卷中的数据仍然存在,不会丢失。
  • 数据共享:多个容器可以同时挂载同一个数据卷,实现数据的共享和交互。
  • 独立于容器生命周期:数据卷的生命周期独立于容器,不受容器的启动、停止和删除的影响。

7.1 为什么要用数据卷

docker分层文件系统
  • 性能差
  • 生命周期与容器相同
docker数据卷
  • mount到主机中,绕开分层文件系统
  • 和主机磁盘性能相同,容器删除后依然保留
  • 仅限本地磁盘,不能随容器迁移
docker提供了两种卷:
  • bind mount
  • docker managed volume

7.2 bind mount 数据卷

  • 是将主机上的目录或文件mount到容器里。
  • 使用直观高效,易于理解。
  • 使用 -v 选项指定路径,格式 :-v选项指定的路径,如果不存在,挂载时会自动创建

bind mount 数据卷

在 Docker 中,Bind Mount(绑定挂载) 是一种将宿主机的文件或目录直接挂载到容器内的方式,属于数据持久化的一种手段。它与 Docker 管理的数据卷(Volume)不同,Bind Mount 完全依赖宿主机的文件系统结构,容器直接访问宿主机的指定路径。

Bind Mount 的核心特点

  1. 直接映射:容器内的路径与宿主机的路径直接绑定,双方的修改会实时同步(无论容器是否运行)。
  2. 依赖宿主机路径:必须指定宿主机的绝对路径(或相对路径,Docker 会自动转换为绝对路径),若路径不存在,Docker 会自动创建(目录)。
  3. 权限控制:可通过 :ro(read-only)设置为只读,默认是读写(rw)。
  4. 无命名管理:Docker 不会对 Bind Mount 进行命名或跟踪,完全由用户管理宿主机路径。

创建测试文件:
 

[root@docker test-2]# echo data1 data1 > data1
[root@docker test-2]# echo data2 data2 > data2[root@docker test-2]# cat data2
data2 data2
[root@docker test-2]# cat data1
data1 data1

进行挂载:

docker run -it --rm \-v ./data1:/data1:rw \       # 1. 读写挂载当前目录下的data1到容器内的/data1-v ./data2:/data2:ro \       # 2. 只读挂载当前目录下的data2到容器内的/data2-v /etc/passwd:/data/passwd:ro \  # 3. 只读挂载宿主机的/etc/passwd到容器内的/data/passwdbusybox                      # 使用的镜像

测试:
data1为可读可写,data2为只读

/ # ls
bin    data   data1  data2  dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # cat data1
data1 data1
/ # cat data2
data2 data2
/ # echo docker 1 >> data1
/ # cat data1
data1 data1
docker 1
/ # echo docker 2 >> data2
sh: can't create data2: Read-only file system
/ # cat data2
data2 data2
/ # exit

退出容器后查看本机刚挂载的目录文件情况:
因为文件为挂载文件,所有在容器内部进行更改后,主机的文件也进行了相应的更改

[root@docker test-2]# cat data1
data1 data1
docker 1
[root@docker test-2]# cat data2
data2 data2

7.3 Docker managed 数据卷

在 Docker 中,Managed Volume(Docker 管理的数据卷) 是由 Docker 引擎自动创建和管理的持久化存储方式,无需用户指定主机上的具体路径,完全由 Docker 负责存储位置的分配和维护。这种方式简化了数据卷的使用,尤其适合需要持久化容器数据但不想手动管理主机文件路径的场景。

Docker Managed Volume 的核心特点

自动创建与管理

  • 无需指定主机目录(如 -v /host/path:/container/path),只需在运行容器时指定容器内的挂载点(如 -v /data),Docker 会自动在主机的特定目录(通常是 /var/lib/docker/volumes/<volume-id>/_data)创建数据卷。
  • 数据卷的生命周期独立于容器,即使容器被删除,数据卷仍会保留,除非手动删除。

持久化存储

  • 容器内写入 /data(假设挂载点为 /data)的数据会被持久化到 Docker 管理的主机目录中,避免容器删除后数据丢失。

与容器解耦

  • 可被多个容器共享和重用,适合多容器协作场景(如数据库容器与应用容器共享数据)

8 Docker的安全加固

[root@docker packages]# free -mtotal        used        free      shared  buff/cache   available
Mem:            3627         721        2411           9         739        2906
Swap:           4011           0        4011
[root@docker packages]# docker run --rm  --memory 200M -it ubuntu:latest 
root@e0d90039aafc:/# free -mtotal        used        free      shared  buff/cache   available
Mem:            3627         756        2377           9         739        2871
Swap:           4011           0        4011

8.1 解决Docker的默认隔离性

安装lxcfs:

[root@docker rpm]# ls
bridge-utils-1.7.1-3.el9.x86_64.rpm  libcgroup-tools-0.41-19.el8.x86_64.rpm  lxc-templates-4.0.12-1.el9.x86_64.rpm
docker.tar.gz                        lxcfs-5.0.4-1.el9.x86_64.rpm
libcgroup-0.41-19.el8.x86_64.rpm     lxc-libs-4.0.12-1.el9.x86_64.rpm
dnf install lxcfs-5.0.4-1.el9.x86_64.rpm lxc-libs-4.0.12-1.el9.x86_64.rpm lxc-templates-4.0.12-1.el9.x86_64.rpm -y

运行lxcfs并解决容器隔离性

[root@docker rpm]# lxcfs /var/lib/lxcfs &
[root@docker rpm]# docker run  -it -m 256m \
-v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
-v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
-v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
-v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
-v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
-v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
ubuntu
root@cc08b2ff703b:/# free -mtotal        used        free      shared  buff/cache   available
Mem:             256           1         254           0           0         254
Swap:              0           0           0

8.2 容器特权

在容器中默认情况下即使我是容器的超级用户也无法修改某些系统设定,比如网络

[root@docker rpm]# docker run --rm -it  busybox
/ # whoami
root
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 9a:f8:5a:46:af:fd brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
/ # ip a a 172.25.254.111/24 dev eth0
ip: RTNETLINK answers: Operation not permitted

这是因为容器使用的很多资源都是和系统真实主机公用的,如果允许容器修改这些重要资源,系统的稳定性会变的非常差

但是由于某些需要求,容器需要控制一些默认控制不了的资源,如何解决此问题,这时我们就要设置容器特权

[root@docker rpm]# docker run --rm -it --privileged busybox
/ # whoami
root
/ # ip a a 172.25.254.111/24 dev eth0
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 7e:d4:04:1d:99:1a brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft foreverinet 172.25.254.111/24 scope global eth0valid_lft forever preferred_lft forever

#如果添加了--privileged 参数开启容器,容器获得权限近乎于宿主机的root用户

8.3 容器特权的白名单

--privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限

capabilities手册地址:capabilities(7) - Linux manual page

#限制容器对网络有root权限

[root@docker rpm]# docker run --rm -it --cap-add NET_ADMIN  busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether e2:87:85:ef:35:9e brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
/ # ip a a 172.25.254.111/24 dev eth0                                 #网络可以设定
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether e2:87:85:ef:35:9e brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft foreverinet 172.25.254.111/24 scope global eth0     valid_lft forever preferred_lft forever
/ # fdisk  -l                                            #无法管理磁盘

9 容器编排工具Docker Compose

9.1 Docker Compose 概述

​​​​​​​

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。
其是官方的一个开源项目,托管到github
https://github.com/docker/compose
网址:
主要功能
1. 定义服务
  • 使用 YAML 格式的配置文件来定义一组相关的容器服务。每个服务可以指定镜像、端口映射、 环境变量、存储卷等参数。
  • 例如,可以在配置文件中定义一个 Web 服务和一个数据库服务,以及它们之间的连接关系。
2. 一键启动和停止
  • 通过一个简单的命令,可以启动或停止整个应用程序所包含的所有容器。这大大简化了多容器 应用的部署和管理过程。
  • 例如,使用 docker-compose up 命令可以启动配置文件中定义的所有服务,使用 dockercompose down 命令可以停止并删除这些服务。
3. 服务编排
  • 可以定义容器之间的依赖关系,确保服务按照正确的顺序启动和停止。例如,可以指定数据库 服务必须在 Web 服务之前启动。
  • 支持网络配置,使不同服务的容器可以相互通信。可以定义一个自定义的网络,将所有相关的 容器连接到这个网络上。
4. 环境变量管理
  • 可以在配置文件中定义环境变量,并在容器启动时传递给容器。这使得在不同环境(如开发、 测试和生产环境)中使用不同的配置变得更加容易。
  • 例如,可以定义一个数据库连接字符串的环境变量,在不同环境中可以设置不同的值。
工作原理
1. 读取配置文件
  • Docker Compose 读取 YAML 配置文件,解析其中定义的服务和参数。
2. 创建容器
  • 根据配置文件中的定义,Docker Compose 调用 Docker 引擎创建相应的容器。它会下载所需 的镜像(如果本地没有),并设置容器的各种参数。
3. 管理容器生命周期
  • Docker Compose 监控容器的状态,并在需要时启动、停止、重启容器。
  • 它还可以处理容器的故障恢复,例如自动重启失败的容器。
Docker Compose 中的管理层
  1. 服务 (service) 一个应用的容器,实际上可以包括若干运行相同镜像的容器实例
  2. 项目 (project) 由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义
  3.  容器(container)容器是服务的具体实例,每个服务可以有一个或多个容器。容器是基于服务定义的镜像创建的运行实例

9.2 Docker Compose 的常用命令参数

[root@docker packages]# cat docker-compose.yml 
services:web:image: nginx:1.23ports:- "80:80"db:image: mysql:5.7environment:MYSQL_ROOT_PASSWORD: rin

以下是一些 Docker Compose 常用命令:

一、服务管理

  1. docker-compose up

    • 启动配置文件中定义的所有服务。

    • 可以使用 -d 参数在后台启动服务。

    • 可以使用-f 来指定yml文件

    • 例如:docker-compose up -d

9.3 企业示例

利用容器编排完成haproxy和nginx负载均衡架构实施

编辑docker-compose.yml文件:
 

[root@docker retest]# cat docker-compose.yml 
services:web1:image: nginx:latestcontainer_name: web1networks:- mynet1expose:- 80volumes:- /docker/web/html1:/usr/share/nginx/htmlweb2:image: nginx:latestcontainer_name: web2networks:- mynet1expose:- 80volumes:- /docker/web/html2:/usr/share/nginx/htmlhaproxy:image: haproxy:2.3container_name: haproxyrestart: alwaysnetworks:- mynet1- mynet2volumes:- /docker/conf/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfgports:- 80:80networks:mynet1:driver: bridgemynet2:driver: bridge

编辑两台web的默认发布命令,文件中将其链接在本机的/docker/web/html1和/docker/web/html2下:

创建默认发布目录文件:

mkdir /docker/web/{html1,html2} -p

编写内容:

echo web1 > /docker/web/html1/index.html
echo web2 > /docker/web/html2/index.html

编辑haproxy的配置文件,并放到容器与主机链接的目录:
创建配置文件目录:

mkdir /docker/conf/haproxy

编辑配置文件:

[root@docker retest]# vim /docker/conf/haproxy/haproxy.cfg 
[root@docker retest]# cat /docker/conf/haproxy/haproxy.cfg 
globallog 127.0.0.1 local0 infomaxconn 4096daemondefaultslog globalmode httpoption httplogoption dontlognullretries 3timeout connect 5stimeout client 30stimeout server 30stimeout check 5slisten http_load_balancerbind *:80balance roundrobinoption httpchk GET /server web1 web1:80 weight 1 maxconn 200 checkserver web2 web2:80 weight 1 maxconn 200 check


挂载相应的镜像:

[root@docker retest]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
nginx                latest    5ef79149e0ec   12 months ago   188MB
haproxy              2.3       7ecd3fda00f4   3 years ago     99.4MB

启动服务栈:

docker compose up -d
[root@docker retest]# docker compose up -d
[+] Running 5/5✔ Network retest_mynet1  Created                                                                                     0.5s ✔ Network retest_mynet2  Created                                                                                     0.5s ✔ Container web2         Started                                                                                     1.0s ✔ Container haproxy      Started                                                                                     2.4s ✔ Container web1         Started                                                                                     1.7s 
[root@docker retest]# docker compose ps
NAME      IMAGE          COMMAND                  SERVICE   CREATED          STATUS          PORTS
haproxy   haproxy:2.3    "docker-entrypoint.s…"   haproxy   11 seconds ago   Up 11 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp
web1      nginx:latest   "/docker-entrypoint.…"   web1      11 seconds ago   Up 11 seconds   80/tcp
web2      nginx:latest   "/docker-entrypoint.…"   web2      11 seconds ago   Up 11 seconds   80/tcp

测试:

[root@docker retest]# curl 172.25.254.10
web1
[root@docker retest]# curl 172.25.254.10
web2
[root@docker retest]# curl 172.25.254.10
web1
[root@docker retest]# curl 172.25.254.10
web2

文章转载自:

http://QHiVAUei.nLysd.cn
http://jYYcM7Ed.nLysd.cn
http://1aUcSbej.nLysd.cn
http://4tGbFkuT.nLysd.cn
http://6YrLAqRI.nLysd.cn
http://ESmfKuCQ.nLysd.cn
http://Iz4WGxeO.nLysd.cn
http://Wh1PUymL.nLysd.cn
http://womfTWZQ.nLysd.cn
http://Cj10qxlU.nLysd.cn
http://OMeXXcf9.nLysd.cn
http://Lz6sL3p8.nLysd.cn
http://bo7AQ2Sk.nLysd.cn
http://sZeciNMU.nLysd.cn
http://mIeGc8US.nLysd.cn
http://te25OftO.nLysd.cn
http://NTcOJcUu.nLysd.cn
http://35VqBsKG.nLysd.cn
http://6gG1HYOQ.nLysd.cn
http://cg0m2tHe.nLysd.cn
http://cnQBvSzf.nLysd.cn
http://kEX8uHaM.nLysd.cn
http://3Wk6QoyJ.nLysd.cn
http://z8StGQtU.nLysd.cn
http://mz8eikl5.nLysd.cn
http://9s5kCsjn.nLysd.cn
http://XlKXQIbP.nLysd.cn
http://FeK1JWS3.nLysd.cn
http://ooDjdl21.nLysd.cn
http://FMGhesdA.nLysd.cn
http://www.dtcms.com/a/384797.html

相关文章:

  • 倍福TwinCAT HMI如何关联PLC变量
  • 2025.9.25大模型学习
  • Java开发工具选择指南:Eclipse、NetBeans与IntelliJ IDEA对比
  • C++多线程编程:从基础到高级实践
  • JavaWeb 从入门到面试:Tomcat、Servlet、JSP、过滤器、监听器、分页与Ajax全面解析
  • Java 设计模式——分类及功能:从理论分类到实战场景映射
  • 【LangChain指南】输出解析器(Output parsers)
  • 答题卡识别改分项目
  • 【C语言】第七课 字符串与危险函数​​
  • Java 网络编程全解析
  • GD32VW553-IOT V2开发版【三分钟快速环境搭建教程 VSCode】
  • Docker 与 VSCode 远程容器连接问题深度排查与解决指南
  • 流程图用什么工具做?免费/付费工具对比,附在线制作与下载教程
  • IT运维管理与服务优化
  • javaweb XML DOM4J
  • 用C#生成带特定字节的数据序列(地址从0x0001A000到0x0001C000,步长0x20)
  • 解析预训练:BERT到Qwen的技术演进与应用实践
  • PCB 温度可靠性验证:从行业标准到实测数据
  • 机器人要增加力矩要有那些条件和增加什么
  • MongoDB 在物联网(IoT)中的应用:海量时序数据处理方案
  • 6U VPX 板卡设计原理图:616-基于6U VPX XCVU9P+XCZU7EV的双FMC信号处理板卡
  • 【芯片设计-信号完整性 SI 学习 1.2.2 -- 时序裕量(Margin)】
  • Elasticsearch核心概念与Java实战:从入门到精通
  • Flink 内部状态管理:PriorityQueueSet解析
  • ChatBot、Copilot、Agent啥区别
  • LeetCode 热题560.和为k的子数组 (前缀和)
  • 掌握多边形细分建模核心技术:从基础操作到实战技巧详解
  • [特殊字符] Python在CentOS系统执行深度指南
  • 机器人控制器开发(定位——cartographer ros2 使用1)
  • 7 制作自己的遥感机器学习数据集