Docker容器技术
Docker简介Docker之父Solomon Hykes:Docker就好比传统的货运集装箱2008 年LXC(LinuX Contiainer)发布,但是没有行业标准,兼容性非常差docker2013年首次发布,由Docker, Inc开发什么是docker?Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术它具有以下几个重要特点和优势:轻量级虚拟化Docker 容器相较
Docker简介
Docker之父Solomon Hykes:Docker就好比传统的货运集装箱
2008 年LXC(LinuX Contiainer)发布,但是没有行业标准,兼容性非常差
docker2013年首次发布,由Docker, Inc开发
什么是docker?
Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术
它具有以下几个重要特点和优势:
轻量级虚拟化
Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。
- 例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。
一致性
确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。
- 无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。
可移植性
可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差异。
- 比如,在本地开发的容器可以无缝部署到云服务器上。
高效的资源利用:
多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资源。
易于部署和扩展:
能够快速部署新的应用实例,并且可以根据需求轻松地进行水平扩展。
总之,Docker 极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。它在现代软件开发和云计算领域得到了广泛的应用。
docker在企业中的应用场景
- 在企业中docker作为业务的最小载体而被广泛应用
- 通过docker企业可以更效率的部署应用并更节省资源
IaaS(Infrastructure as a Service),即基础设施即服务
PaaS是(Platform as a Service)即指平台即服务
SaaS(Software as a Service)软件运营服务
docker与虚拟化的对比
docker的优势
- 对于开发人员:Build once、Run anywhere。
- 对于运维人员:Configure once、Run anything
- 容器技术大大提升了IT人员的幸福指数!
部署第一个容器
配置软件仓库
# cd /etc/yum.repos.d
# vim docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable
gpgcheck=0
安装docker-ce并启动服务
# yum install -y docker-ce
# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
# systemctl enable --now docker
# docker info
激活内核网络选项
# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
# modprobe br_netfilter
# 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 查看结果:
# echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf 【开启内核参数】
# sysctl -p
# systemctl restart docker
Docker的基本操作
镜像的下载
# docker search nginx 【搜索镜像】
# docker pull nginx:1.26 【拉取镜像】
# docker history nginx 【查看镜像文件】
# docker image inspect nginx:1.23 【查看镜像详细信息】
# docker image save nginx:latest -o nginx-latest.tar.gz 【导出镜像】
# docker images 【查看本地镜像】
保存镜像
# docker save -o `docker images | awk 'NR>1{print $1":"$2}'` images.tar.gz
- -o:指定导出镜像的位置;
- 可以同时导出多个镜像到一个文件中;
- 指定.tar.gz 可以导出并压缩。
删除镜像
# docker rmi nginx:latest
# docker rmi `docker images | awk 'NR>1{print $1":"$2}'` 【删除所有】
容器的常用操作
# docker load -i busybox-latest.tar.gz 【加载镜像到本地镜像库】
# docker load -i nginx-1.23.tar.gz
# docker run -d --name mario -p 80:8080 timinglee/mario 【创建启动一个新容器】
访问网址172.25.254.10:8080
# docker run -it --name centos7 centos:7
进入到容器中,按<ctrl>+<d>退出并停止容器,#按<ctrl>+<pq>退出但不停止容器
在容器中执行命令
# docker attach centos7 【重新进入容器】
# docker ps 【查看正在运行的容器】
# docker ps -a 【查看所有容器】
# docker stop mario 【停止】
# docker kill mario
# docker start mario 【开启停止的容器】
注意:容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态
# docker rm -f mario 【强制删除】
# docker rm centos7 【删除停止的容器】
# docker container prune -f 【删除所有停止的容器】
参数:
-d #后台运行
-i #交互式运行
-t #打开一个终端
--name #指定容器名称
-p #端口映射 -p 80:8080 把容器8080端口映射到本机80端口
--rm #容器停止自动删除容器
--network #指定容器使用的网络
容器内容提交
默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件
如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像
当我们在运行新镜像后即可看到我们提交的内容
# docker run -it --name test busybox 【进入容器】
/ # touch lee 【可以容器内创建文件】
# docker rm test
# docker run -it --name test busybox 【删掉容器后开启新的容器文件不存在】
系统中的文件和容器中的文件传输
# docker cp test2:/leefile /mnt 【把容器中的文件复制到本机】
# docker cp /etc/fstab test2:/fstab 【把本机文件复制到容器中】
查询容器内部日志
# docker logs centos7 【查看日志】
docker镜像构建
docker镜像结构
共享宿主机的kernel
base镜像提供的是最小的Linux发行版
同一docker主机支持运行多种Linux发行版
采用分层结构的最大好处是:共享资源
镜像运行的基本原理
Copy-on-Write 可写容器层
容器层以下所有镜像层都是只读的
docker从上往下依次查找文件
容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
一个镜像最多127层
镜像获得方式
基本镜像通常由软件官方提供
企业镜像可以用官方镜像+Dockerfile来生成
系统关于镜像的获取动作有两种:
docker pull 镜像地址
docker load –i 本地镜像包
镜像构建
构建参数
COPY 复制文件 eg:COPY file /file 或者 COPY [“file”,”/”]
MAINTAINER 指定作者信息,比如邮箱 eg:MAINTAINER user@example.com<br />在最新版的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功能和用法类似,但动作不可被覆盖
参数示例及用法
# mkdir /root/docker/
# cd /root/docker/
# touch leefile
# vim Dockerfile
FROM busybox:latest #指定使用的基础镜像
MAINTAINER lee@timinglee.org #指定作者信息
COPY leefile / #复制当前目录文件到容器指定位置,leefile必须在当前目录中
#ADD leefile.gz /
# docker build -t example:v1 【构建镜像】
# touch leefile{1..3}
# tar zcf leefile.gz leefile*
# vim Dockerfile
ADD leefile.gz / ##取消格式化
# docker build -t example:v2 .
# docker rm -f test 2>/dev/null 【清理容器】
# docker run -it --rm --name test example:v2 【使用镜像】
# vim Dockerfile
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
CMD echo $NAME
# docker build -t example:v3 .
# docker run -it --rm --name test example:v3
# vim Dockerfile
ENV NAME lee
CMD ["/bin/echo", "$NAME"]
# vim Dockerfile
ENV NAME lee
CMD ["/bin/sh", "-c", "/bin/echo $NAME"]
# vim Dockerfile
#ENTRYPOINT
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
ENTRYPOINT echo $NAME
# vim Dockerfile
#EXPOSE VOLUME VOLUME
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
EXPOSE 80 443
VOLUME /var/www/html
WORKDIR /var/www/html
RUN touch leefile
Dockerfile建立
建立构建目录,编写构建文件
# cd /root/docker/
# cp /mnt/packages/nginx-1.23.tar.gz .
# vim Dockerfile
FROM centos:7
ADD nginx-1.23.tar.gz /mnt
WORKDIR /mnt/nginx-1.23
RUN yum install -y gcc make pcre-devel openssl-devel
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
通过dockerfile生成镜像
# docker build -t webserver:v1 .
测试镜像可用性
# docker images webserver
# docker history webserver:v1
# docker run -d --name checkimage webserver
查看容器详情
# docker inspect web1
镜像优化方案
镜像优化策略
选择最精简的基础镜像,减少镜像的层数,清理镜像构建的中间产物,选择最精简基础镜像 ,减少镜像的层数,清理镜像构建的中间产物
镜像优化示例
缩减镜像层
# vim Dockerfile
FROM centos:7 as build
ADD nginx-1.23.tar.gz /mnt
WORKDIR /mnt/nginx-1.23
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 && yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
# docker build -t webserver:v1 .
# docker images webserver
多阶段构建
# vim Dockerfile
FROM centos:7 as lee
ADD nginx-1.23.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 && 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;"]
# docker build -t webserver:v2 .
# docker images webserver
利用最精简镜像构建
# docker load -i /mnt/packages/debian11.tar.gz
# vim Dockerfile
FROM nginx:1.23 AS base
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 &&
FROM gcr.io/distroless/base-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
# docker build -t nginx:lee 【构建很快】
# docker images nginx 查看结果:
docker 镜像仓库的管理
什么是docker仓库
Docker 仓库(Docker Registry)是用于存储和分发 Docker 镜像的集中式存储库。
它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。
Docker 仓库可以分为公共仓库和私有仓库:
公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在Docker Hub 上提供的镜像,方便用户直接获取和使用。
例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。
私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。
比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中,以保证安全性和控制访问权限。
通过 Docker 仓库,开发者能够方便地共享和复用镜像,加速应用的开发和部署过程。
docker hub
Docker Hub 是 Docker 官方提供的一个公共的镜像仓库服务。
它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,有大量官方和社区贡献的镜像。
以下是 Docker Hub 的一些关键特点和优势:
1. 丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用的镜像。
例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库的镜像。
2. 官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。
3. 社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。
4. 版本管理:对每个镜像通常都有多个版本可供选择,方便用户根据需求获取特定版本。
5. 便于搜索:用户可以通过关键词轻松搜索到所需的镜像。
docker hub的使用方法 【不常用】
# docker login 【使用公有的仓库】
# ls .docker/
config.json
# docker tag gcr.io/distroless/base-debian11:latest timinglee/base-debian11:latest
# docker push timinglee/base-debian11:latest 【推送】
docker仓库的工作原理
仓库中的三个角色
index docker索引服务,负责并维护有关用户帐户,镜像校验以及公共命名空间的信息。
registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证
Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。
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的请求传递镜像到客户端
push原理
镜像上传的步骤:
1.client向index发送上传请求并完成用户认证
2.index会发方token给client来证明client的合法性
3.client携带index提供的token连接Registry
4.Registry向index合适token的合法性
5.index证实token的合法性
6.Registry开始接收客户端上传过来的镜像
搭建docker的私有仓库
为什么搭建私有仓库
docker hub虽然方便,但是还是有限制
需要internet连接,速度慢
所有人都可以访问
由于安全原因企业不允许将镜像放到外网
好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库
搭建简单的Registry仓库
下载Registry镜像
# docker pull registry 【下载镜像】
# docker load -i /mnt/packages/registry.tag.gz 【建立镜像】
# docker images | grep registry 【查看镜像】
# docker run -d -p 5000:5000 --restart=always --name registry registry 【开启Registry】
# docker ps 【查看开启】
# docker logs registry 【查看仓库有无问题】
# docker tag busybox:latest 172.25.254.10:5000/busybox:latest 【给仓库打标签】
# docker push 172.25.254.10:5000/busybox:latest 【查看推送】
# vim /etc/docker/daemon.json
"insecure-registries": ["172.25.254.10:5000"] ## 添加内容
# systemctl restart docker
上传镜像
# docker push 172.25.254.10:5000/busybox:latest 【上传镜像,几乎无延迟】
# curl 172.25.254.10:5000/v2/_catalog 【查看镜像上传】
# docker pull 172.25.254.10:5000/busybox:latest 【可以直接快速拉取镜像】
为Registry提供加密传输
生成认证key和证书
# mkdir -p /root/data/certs 【创建目录】
# docker stop registry 【关闭仓库容器,发布后面配置】
# docker rm registry
# vim /etc/hosts
# openssl req -newkey rsa:4096 -nodes -sha256 -keyout /root/data/certs/timinglee.org.key -addext "subjectAltName = DNS:reg.timinglee.org" -x509 -days 365 -out /root/data/certs/timinglee.org.crt
# docker run -d -p 443:443 --restart=always --name registry -v /root/data/certs:/certs -v /opt/registry:/var/lib/registry -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:latest
# docker push reg.timinglee.org/busybox:latest
# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
# cp /root/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
# systemctl restart docker
# curl -k https://reg.timinglee.org/v2/_catalog 查看结果:
配置另一台主机好docker
node2 ]# dnf remove podman -y
# dnf install iptables-services -y
# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
dock1 ]# dnf install httpd-tools -y
# mkdir -p /root/auth
# htpasswd -Bc /root/auth/htpasswd timinglee 【创建仓库,更改密码,只有 -B是添加仓库】
# docker run -d -p 443:443 --restart=always --name registry -v /opt/registry:/var/lib/registry -v /root/data/certs:/certs -v /root/auth:/auth -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 -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry:latest
# curl -k https://reg.timinglee.org/v2/_catalog -u timinglee:lee 查看结果:
# vim /etc/docker/daemon.json 【配置解析】
# docker login reg.timinglee.org 【登录仓库】
# ls /root/.docker/ 【查看登录目录】
node2 ]# docker pull reg.timinglee.org/busybox
# mkdir -p /etc/docker/certs.d/reg.timinglee.orgsudo 【创建证书目录】
# scp root@172.25.254.10:/root/data/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
# systemctl restart docker
# docker pull reg.timinglee.org/busybox 查看结果:
构建企业级私有仓库
Harbor 是由vmware公司开源的企业级 Docker Registry 项目。
它提供了以下主要功能和特点:
基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理的灵活性。
镜像复制:支持不同 Harbor 实例间复制镜像,方便在多个数据中心或环境中分发镜像。
图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。
审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
垃圾回收:可以清理不再使用的镜像,节省存储空间。
部署harbor
# cp /mnt/packages/harbor-offline-installer-v2.5.4.tgz /root/
# cd harbor/
# cp harbor.yml.tmpl harbor.yml
# vim harbor.yml 【配置安装文件格式】
# docker rm -f registry 【删除使用的仓库容器】
# docker logout reg.timinglee.org 【退出登录】
# mkdir -p /data/harbor 【创建安装目录】
# ./install.sh --with-chartmuseum 【安装】
# docker compose stop 【停止】
# docker compose up -d 【开启】
管理仓库
建立仓库项目
# docker login reg.timinglee.org
# docker tag busybox:latest reg.timinglee.org/timinglee/busybox:latest
# docker images | grep busybox 查看结果:
# docker push reg.timinglee.org/timinglee/busybox:latest
Docker 网络
docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分
docker安装后会自动创建3种网络:bridge(桥接网桥)、host(直连)、none
# docker network ls
docker原生bridge网路
docker安装时会创建一个名为docker0的Linux bridge,新建的容器会自动桥接到这个接口
# ip link show type bridge
bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。
容器通过宿主机的NAT规则后可以访问外网
# docker run -d --name web nginx:1.23
# ifconfig
# iptables -t nat -Ln 查看结果:
# docker stop nginx
# docker run -d --name web -p 8080:80 nginx:1.23
# iptables -t nat -Ln 查看结果:
docker原生网络host
host网络模式需要在容器创建时指定 --network=host
host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性
# docker run -it --name test --rm busybox:latest
/ # ifconfig
# docker run -it --name test --rm --network host busybox:latest
/ # ifconfig
/ # exit
# ifconfig 查看网络:
docker 原生网络none
# docker run -it --name test --rm --network none busybox:latest
/ # ifconfig
docker的自定义网络
自定义网络模式,docker提供了三种自定义网络驱动:
bridge , overlay , macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,
overlay和macvlan是用于创建跨主机网络
建议用自定义的网络控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
自定义桥接网络
在建立自定以网络时,默认使用桥接模式
# docker network create mybridge
# docker network ls
桥接默认是单调递增
# ifconfig
桥接也支持自定义子网和网关
# docker network create mybridge2 --subnet 192.168.0.0/24 --gateway 192.168.0.100
# docker network inspect mybridge2
为什么要自定义桥接
多容器之间如何互访通过ip就可以,但是有什么问题
# docker run -d --name test1 nginx
# docker run -d --name test2 nginx
# docker inspect (test1 / test2)
# docker stop test1 test2
# docker start test2
# docker start test1 【会发现容器ip颠倒】
docker引擎在分配ip时时根据容器启动顺序分配到,谁先启动谁用,是动态变更的
多容器互访用ip很显然不是很靠谱,那么多容器访问一般使用容器的名字访问更加稳定
docker原生网络是不支持dns解析的,自定义网络中内嵌了dns
# docker run -d --network my_net1 --name web nginx 【运行创建web服务】
# docker run -it --network my_net1 --name test busybox 【运行box镜像】
/ # ping web
不同的自定义网络是不能通讯的
在rhel7中使用的是iptables进行网络隔离,在rhel9中使用nftpables
# nft list ruleset 【可以看到网络隔离策略】
如何让不同的自定义网络互通?
确定网络纯净
# docker network create mynet1 【创建网桥】
# docker network create mynet2
# docker run -d --name web1 --network mynet2 nginx 【运行容器】
# docker run -it --name test --network mynet1 busybox
# docker network connect mynet2 test 【连接网络】
# docker start test 【开启停止的容器】
# docker attach test 【重新加入容器】
joined容器网络
Joined容器一种较为特别的网络模式,•在容器创建时使用--network=container:vm1指定。(vm1指定的是运行的容器名)
处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
# docker run -d --name web1 -p 80:80 nginx 【创建wbe服务】
# docker run -it --rm --network container:web1 busybox
/ # ifconfig
# docker run -it --rm --network container:web1 centos:7
# curl localhost 【连接访问】
/]# ping web1 查看结果:
joined网络示例演示
利用容器部署phpmyadmin管理mysql
# docker load -i /mnt/mysql-5.7.tar.gz
# docker load -i /mnt/phpmyadmin-latest.tar.gz
# docker network create my_net1 【创建网络】
# docker ps -a | grep -E 'mysql|mysqladmin' 【确认无输出】
# docker run -d --name mysqladmin --network my_net1 -p 80:80 phpmyadmin:latest -e PMA_ARBITRARY=1 #在web页面中可以手动输入数据库地址和端口
# docker run -d --name mysql \ -e MYSQL_ROOT_PASSWORD='lee' \ #设定数据库密码
mysql:5.7 --network container:mysqladmin \ #把数据库容器添加到phpmyadmin容器中
开启的phpmyadmin容器中是没有数据库的
这里填写的localhost:3306是因为mysql容器和phpmyadmin容器公用一个网络站
容器内外网的访问
容器访问外网
在rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网
在rhel7之后的版本中通过nftables添加地址伪装来访问外网
# iptables -t nat -nL
# w -i
外网访问docker容器
20 ~]# docker run -d --name webserver -p 8080:80 nginx
# ps aux | grep docker 【查看代理】
10 ~]# curl -v 172.25.254.20:8080 【现在可以访问】
20 ~]# kill 9 7105 【删除代理】
10 ~]# curl -v 172.25.254.20:8080 【依然可以访问】
20 ~]# iptables -t nat -nL 【策略还在,代理没有依然可以访问】
# iptables -t nat -D DOCKER 2 【删除DOCKER 的策略2】
# iptables -t nat -nL 查看结果:
10 ~]# curl -v 172.25.254.20:8080
docker-proxy和dnat在容器建立端口映射后都会开启,那个传输速录高走那个
docker跨主机网络
在生产环境中,我们的容器不可能都在同一个系统中,所以需要容器具备跨主机通信的能力
跨主机网络解决方案
docker原生的overlay和macvlan
第三方的flannel、weave、calico
众多网络方案是如何与docker集成在一起的
libnetwork docker容器网络库
CNM (Container Network Model)这个模型对容器网络进行了抽象
CNM (Container Network Model)
NM分三类组件
Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)
Endpoint:作用是将sandbox接入network (veth pair)
Network:包含一组endpoint,同一network的endpoint可以通信
macvlan网络方式实现跨主机通信
macvlan网络方式
Linux kernel提供的一种网卡虚拟化技术。
无需Linux bridge,直接使用物理接口,性能极好
容器的接口直接与主机网卡连接,无需NAT或端口映射。
macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094
macvlan网络间的隔离和连通
macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的
可以在三层上通过网关将macvlan网络连通起来
docker本身不做任何限制,像传统vlan网络那样管理即可
实现macvlan
在两台docker主机上各添加一块网卡(两个都有个仅主机模式网卡),打开网卡混杂模式:
所有主机 ]# docker compose down
# 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
10 ]# docker run -it --name busybox10 --network macvlan1 --ip 1.1.1.100 --rm busybox
/ # ping 1.1.1.200 运行结果:
20 ]# docker run -it --name busybox20 --network macvlan1 --ip 1.1.1.200 --rm busybox
/ # ping 1.1.1.100 运行结果:
Docker 数据卷管理及优化
Docker 数据卷是一个可供容器使用的特殊目录,它绕过了容器的文件系统,直接将数据存储在宿主机上。
这样可以实现以下几个重要的目的:
数据持久化:即使容器被删除或重新创建,数据卷中的数据仍然存在,不会丢失。
数据共享:多个容器可以同时挂载同一个数据卷,实现数据的共享和交互。
独立于容器生命周期:数据卷生命周期独立于容器,不受容器启动、停止和删除的影响。
为什么要用数据卷
docker分层文件系统
性能差
生命周期与容器相同
docker数据卷
mount到主机中,绕开分层文件系统
和主机磁盘性能相同,容器删除后依然保留
仅限本地磁盘,不能随容器迁移
docker提供了两种卷:
bind mount
docker managed volume
bind mount 数据卷
是将主机上的目录或文件mount到容器里。
使用直观高效,易于理解。
使用 -v 选项指定路径
-v选项指定的路径,如果不存在,挂载时会自动创建
# echo "hello data1" > /tmp/data1
# echo "hello data2" > /tmp/data2
# docker run -it --name test --rm -v /tmp/data1:/data1:rw -v /tmp/data1:/data2:ro busybox:latest
docker managed 数据卷
bind mount必须指定host文件系统路径,限制了移植性
docker managed volume 不需要指定mount源,docker自动为容器创建数据卷目录
默认创建的数据卷目录都在 /var/lib/docker/volumes 中
如果挂载时指向容器内已有的目录,原有数据会被复制到volume中
# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='lee' mysql:5.7
# ls -l /var/lib/docker/volumes
# docker exec -it mysql bash 【运行容器启动mysql】
# ls
# exit
# docker rm -f mysql 【删除数据库数据不会消失】
# ls /var/lib/docker/volumes/5bc04 … 2b622/_data/# cd /var/lib/mysql
# docker volume prune 【删除没有使用的卷】
在执行 docker volume prune 命令之前,请确保你确实不再需要这些数据卷中的数据,因为该操作是不可逆的,一旦删除数据将无法恢复。
如有重要数据存储在数据卷中,建议先备份,或者确保数据已经被妥善保存到其他地方。
建立数据卷
# docker volume create leevol1 【创建卷】
# ls -l /var/lib/docker/volumes/leevol1/_data/
查看卷
# docker volume ls
使用建立的数据卷
# docker run -d --name web1 -p 80:80 -v leevol1:/usr/share/nginx/html nginx
# ls /var/lib/docker/volumes/leevol1/_data
# echo leevol1 > /var/lib/docker/volumes/leevol1/_data/index.html
# curl 172.25.254.20 查看结果:
使用外挂载卷
# vim /var/lib/docker/volumes/5bc04 … 2b622/_data/conf.d/bbs.conf 【配置挂载卷】
server {
listen 80;
server_name bbs.timinglee.org;
root /usr/share/nginx/html;
index bbs.html;
}
# echo "bbs.html" > /var/lib/docker/volumes/voll/_data/bbs.html
# vim /etc/hosts
# docker run -d --name nginx-bbs -p 8080:80 -v voll:/usr/share/nginx/html -v nginxconf:/etc/nginx nginx:latest
数据卷容器(Data Volume Container)
数据卷容器(Data Volume Container)是 Docker 中一种特殊的容器,主要用于方便地在多个容器之间共享数据卷。
建立数据卷容器
# docker run -d --name nginx-bbs -p 8080:80 -v /etc/nginx/conf.d/bbs.conf:/etc/nginx/conf.d/bbs.conf:ro -v /usr/share/nginx/html:/usr/share/nginx/html:ro nginx:latest
使用数据卷容器
# docker run -it --name test --rm --volumes-from datavol busybox 【使用容器查看数据】
/ # ls
/ # cat /etc/resolv.conf
/ # touch data1/leefile1
/ # touch /data2/leefile1 【是文件不是目录,无法创建】
bind mount 数据卷和docker managed 数据卷的对比
相同点:
两者都是 host 文件系统中的某个路径
不同点:
备份与迁移数据卷
备份数据卷
# docker run --volumes-from datavol \
-v `pwd`:/backup busybox \ #把当前目录挂在到容器中用于和容器交互保存要备份的容器
tar zcf /backup/data1.tar.gz /data1 #备份数据到本地
数据恢复
# docker run -it --name test -v leevol1:/data1 -v `pwd`:/backup busybox /bin/sh -c "tar zxf /backup/data1.tar.gz;/bin/sh"
/ # ls data1/
Docker 的安全优化
Docker容器的安全性,很大程度上依赖于Linux系统自身
评估Docker的安全性时,主要考虑这几个方面: Linux内核的命名空间机制提供的容器隔离安全。 Linux控制组机制对容器资源的控制能力安全。 Linux内核的能力机制所带来的操作权限安全。 Docker程序(特别是服务端)本身的抗攻击性。 其他安全增强机制对容器安全性的影响。
在rhel9中默认使用cgroup-v2 但是cgroup-v2中不利于观察docker的资源限制情况,所以推荐使用cgroup-v1
# grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"
命名空间隔离的安全
当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了最基础也最直接的隔离。
与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底。
容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。
在 Linux 内核中,有很多资源和对象不能被Namespace化,比如:cpu信息,磁盘等
# docker run -d --name web nginx
# docker inspect web | grep Pid
# ls /proc/9267/ns/
# mount -t cgroup2
# reboot
控制组资源控制的安全
当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源。
确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击(DDoS)方面必不可少
# free -m
# docker run -it --name test busybox
/ # free -m
内核能力机制
能力机制(Capability)是Linux内核一个强大的特性,可以提供细粒度的权限访问控制。
大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可。
默认情况下,Docker采用“白名单”机制,禁用“必需功能”之外的其他权限。
Docker服务端防护
使用Docker容器的核心是Docker服务端,确保只有可信的用户才能访问到Docker服务。
将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题。
允许Docker 服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。
这些子进程只允许在特定范围内进行操作。
# ls -ld /var/lib/docker/
# docker run -it --name test busybox
然后ctrl + pq,这样容器运行可以查看不在容器内的信息
Docker的资源限制
Linux Cgroups 的全称是 Linux Control Group。
是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。
对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。
Linux Cgroups 给用户暴露出来的操作接口是文件系统
它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。
执行此命令查看:mount -t cgroup
# mount -t cgroup
# ls /sys/fs/cgroup/
在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。
在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。
控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定。
限制cpu使用
限制cpu的使用量
# docker load -i /mnt/packages/ubuntu-latest.tar.gz
# docker run -it --name test --rm ubuntu:latest 【不限制cpu启动容器】
/# top
# docker run -it --rm --name test --cpu-period 100000 --cpu-quota 20000 ubuntu 【限制cpu】
/# dd if=/dev/zero of=/dev/null & 【测试占用进程,没有限制会占用大量进程】
# top
# cat /sys/fs/cgroup/system.slice/docker- …… .scope/cpu.max 【查看docker的资源限制】
# ls /sys/fs/cgroup/cpu/docker/398195 …… 50aa3f/ 【查看cpu限制目录】
# cat /sys/fs/cgroup/cpu/docker/398195 …… 50aa3f/cpu.cfs_quota_us 【查看限制】
# echo "30000" > /sys/fs/cgroup/cpu/docker/398195 ……/cpu.cfs_quota_us 【更改限制值】
限制cpu的优先级
关闭cpu的核心,当cpu都不空闲下才会出现争抢的情况,为了实验效果我们可以关闭一个cpu核心
# echo 0 > /sys/devices/system/cpu/cpu1/online 【cpu下线】
# cat /proc/cpuinfo
# docker run -it --rm --cpu-shares ubuntu
/# dd if=/dev/zero of=/dev/null &
# docker run -it --rm --cpu-shares 100 ubuntu 【设定cpu优先级】
/# dd if=/dev/zero of=/dev/null &
/# top
限制内存使用
# docker run -d --name test --memory 200M --memory-swap 200M nginx
【大小和资源不超过200M】
# cat /sys/fs/cgroup/memory/docker/7002197a …… 3d7e65/memory.limit_in_bytes
# cat /sys/fs/cgroup/memory/docker/7002197a …… 3d7e65/memory.memsw.limit_in_bytes
测试容器内存限制,在容器中我们测试内存限制效果不是很明显,可以利用工具模拟容器在内存中写入数据。
在系统中/dev/shm这个目录被挂在到内存中。
# dnf install /mnt/packages/rpm/*.rpm -y
# cd /sys/fs/cgroup/memory
# cgexec -g memory:docker/7002197a …… 3d7e65 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=150
# cgexec -g memory:docker/7002197a …… 3d7e65 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
# echo 209715200 > memory.limit_in_bytes 【内存可用大小能修改限制】
# cat tasks 【进程被调用】
# free -m 查看:
# cgexec -g memory:docker/7002197a …… 3d7e65 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=300
# free -m 查看:
# echo 209715200 >memory.memsw.limit_in_bytes
cgexec -g memory:doceker/容器id -g表示使用指定控制器类型
限制docker的磁盘io
# df -h
# docker run -it --name test --rm --device-write-bps /dev/sda:30M ubuntu
/# dd if=/dev/zero of=bigfile 【测试运行】
/# dd if=/dev/zero of=bigfile bs=1M count=100 【生成测试文件】
/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct
Docker的安全加固
解决Docker的默认隔离性
LXCFS 是一个为 LXC(Linux Containers)容器提供增强文件系统功能的工具。
主要功能
1. 资源可见性:
LXCFS 可以使容器内的进程看到准确的 CPU、内存和磁盘 I/O 等资源使用信息。在没有 LXCFS时,容器内看到的资源信息可能不准确,这会影响到在容器内运行的应用程序对资源的评估和管理。
2. 性能监控:
方便对容器内的资源使用情况进行监控和性能分析。通过提供准确的资源信息,管理员和开发人员可以更好地了解容器化应用的性能瓶颈,并进行相应的优化。
# dnf install /mnt/packages/rpm/lxc*.rpm -y
运行lxcfs并解决容器隔离性
# lxcfs /var/lib/lxcfs &
# free -m
# 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 ubuntu
/# free -m
容器特权
在容器中默认情况下即使我是容器的超级用户也无法修改某些系统设定,比如网络
# docker run --rm -it busybox:latest
/ # whoami
/ # ip a
/ # ip a a 192.168.0.10/24 dev eth0
/ # fdisk -l 【查看硬盘设备】
这是因为容器使用的很多资源都是和系统真实主机公用的,如果允许容器修改这些重要资源,系统的稳定性会变的非常差
但是由于某些需要求,容器需要控制一些默认控制不了的资源,如何解决此问题,这时我们就要设置容器特权
# docker run --rm -it --privileged busybox:latest
/ # id root
/ # ip a a 192.168.0.10/24 dev eth0
/ # ip a
/ # fdisk -l
如果添加--privileged参数开启容器,容器获得权限近乎于宿主机的root用户,非常不安全
容器特权的白名单
--privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限
# docker run --rm -it --cap-add NET_ADMIN busybox:latest
/ # fdisk -l
容器编排工具Docker Compose
Docker Compose 概述
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。
其是官方的一个开源项目,托管到github上
主要功能
1. 定义服务:
使用 YAML 格式的配置文件来定义一组相关的容器服务。每个服务可以指定镜像、端口映射、环境变量、存储卷等参数。
例如,在配置文件中定义一个 Web 服务和一个数据库服务,以及它们之间的连接关系。
2. 一键启动和停止:
通过一个简单的命令,可以启动或停止整个应用程序所包含的所有容器。这大大简化了多容器应用的部署和管理过程。
例如,使用 docker-compose up 命令可以启动配置文件中定义的所有服务,使用 docker
compose 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)容器是服务的具体实例,每个服务可以有一个或多个容器。容器是基于服务定义的镜像创建的运行实例
Docker Compose 的常用命令参数
# vim docker-compose.yml
services:
web:
image: nginx
ports:
- "80:80"
busybox:
image: busybox:latest
environment:
filename: lee
command: ["/bin/sh", "-c", "touch ${filename}; sleep 1000"]
#MYSQL_ROOT_PASSWORD: lee
以下是一些 Docker Compose 常用命令:
服务管理
docker-compose up :
启动配置文件中定义的所有服务。
可以使用 -d 参数在后台启动服务。
可以使用-f 来指定yml文件
例如: docker-compose up -d 。
# docker compose -f docker-compose.yml up -d
docker-compose start :
启动已经存在的服务,但不会创建新的服务。
# docker compose -f docker-compose.yml start
docker-compose stop :
停止正在运行的服务
# docker compose -f docker-compose.yml stop
docker-compose down :
停止并删除配置文件中定义的所有服务以及相关的网络和存储卷。
# docker compose -f docker-compose.yml down
docker-compose restart :
重启服务。
# docker compose -f docker-compose.yml restart
服务状态查看
docker-compose ps :
列出正在运行的服务以及它们的状态,包括容器 ID、名称、端口映射等信息。
# docker compose -f docker-compose.yml ps
docker-compose logs :
查看服务的日志输出。可以指定服务名称来查看特定服务的日志
# docker compose -f docker-compose.yml logs
构建和重新构建服务
docker-compose build :
构建配置文件中定义的服务的镜像。可以指定服务名称来只构建特定的服务。
# vim Dockerfile
# vim docker-compose.yml
services:
test1:
image: lee1 #生成镜像名称
build:
context: /root/lee #指定Dockerfile位置
dockerfile: lee.Dockerfile #指定Dockerfile名字
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
# docker compose -f docker-compose.yml build 【构建镜像】
# docker compose -f docker-compose.yml build test1 【构建test1镜像】
docker-compose up --build :
启动服务并在启动前重新构建镜像。
# docker compose -f docker-compose.yml up -d
# docker compose -f docker-compose.yml up --build 【先启动镜像再构建容器】
其他操作
docker-compose exec :
在正在运行的服务容器中执行命令。
# vim docker-compose.yml
services:
test:
image: busybox
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
# docker compose -f docker-compose.yml up -d
# docker compose -f docker-compose.yml exec test sh
docker-compose pull :
拉取配置文件中定义的服务所使用的镜像。
# docker compose -f docker-compose.yml pull
docker-compose config :
验证并查看解析后的 Compose 文件内容
# docker compose -f docker-compose.yml config
# docker compose -f docker-compose.yml config -q
Docker Compose 的yml文件
Docker Compose 的 YAML 文件用于定义和配置多容器应用程序的各个服务。以下是一个基本的Docker Compose YAML 文件结构及内容解释:
服务(services)
服务名称(service1_name/service2_name 等):
每个服务在配置文件中都有一个唯一的名称,用于在命令行和其他部分引用该服务。
# vim ~/.vimrc
# vim docker-compose.yml
services:
web:
# 服务1的配置
mysql:
# 服务2的配置
镜像(image):
指定服务所使用的 Docker 镜像名称和标签。例如, image: nginx:latest 表示使用 nginx
镜像的最新版本
# vim docker-compose.yml
services:
web:
images:nginx
mysql:
images:mysql:5.7
端口映射(ports):
将容器内部的端口映射到主机的端口,以便外部可以访问容器内的服务。
# vim docker-compose.yml
services:
mysql:
images: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: lee
container_name: mysql
# docker compose -f docker-compose.yml up -d
# docker compose down
# vim docker-compose.yml
services:
mysql:
images: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: lee
container_name: mysql
expose:
- "8080"
# docker compose -f docker-compose.yml up -d
# docker compose ps -a 查看结果:
环境变量(environment):
为容器设置环境变量,可以在容器内部的应用程序中使用。例如, VAR1: value1 设置环境变量 VAR1 的值为 value1
# vim docker-compose.yml
services:
web:
images:mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: lee
存储卷(volumes):
将主机上的目录或文件挂载到容器中,以实现数据持久化或共享。例如, -
/host/data:/container/data 将主机上的 /host/data 目录挂载到容器内 /container/data 路径。
# vim docker-compose.yml
services:
test:
image: busybox
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
volumes:
- /etc/passwd:/tmp/passwd:ro
# docker compose down
# docker compose -f docker-compose.yml up -d
# docker exec -it busybox1 cat /tmp/passwd 【查看挂载内容】
网络(networks)
将服务连接到特定的网络,以便不同服务的容器可以相互通信
# vim docker-compose.yml
services:
busybox:
image: busybox:latest
container_name: busybox
command: ["/bin/sh","-c","sleep3000"]
networks:
- mynet1
- mynet2
networks:
mynet1:
driver: bridge
mynet2:
driver: bridge
# docker compose down
# docker compose -f docker-compose.yml up -d
# docker network ls
# docker compose exec busybox sh
/ # ifconfig 查看结果:
命令(command):
覆盖容器启动时默认执行的命令。例如, command: python app.py 指定容器启动时运行python app.py 命令
# command: ["/bin/sh","-c","sleep3000"]
#或# command:
# - /bin/sh
# - -c
# - sleep3000
网络服务(networks):
定义 Docker Compose 应用程序中使用的网络。可以自定义网络名称和驱动程序等属性。
默认情况下docker compose 在执行时会自动建立网路
# vim docker-compose.yml
services:
busybox:
image: busybox:latest
container_name: busybox
command: ["/bin/sh","-c","sleep 3000"]
network_mode: default
networks:
default:
external: true
name: bridge
# docker compose down
# docker compose -f docker-compose.yml up -d
# docker network ls 【显示没有建立】
# vim docker-compose.yml
# docker compose down
# docker compose -f docker-compose.yml up -d
# docker network ls 查看建立:
# docker compose exec busybox sh
/ # ifconfig 查看结果:
/ # route -n
存储卷(volumes)
定义 Docker Compose 应用程序中使用的存储卷。可以自定义卷名称和存储位置等属性。
# vim docker-compose.yml
services:
test:
image: busybox
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
volumes:
- data:/mnt #挂在/mnt/
volumes:
data:
name: lee
# docker compose down
# docker compose -f docker-compose.yml up -d
# docker volume ls 查看结果:
利用容器编排完成haproxy和nginx负载均衡架构实施
软件下载:
# dnf install haproxy-2.4.22-3.el9_3.x86_64 --downloadonly --destdir /mnt/ -y
# rpm2cpio /mnt/haproxy-2.4.22-3.el9_3.x86_64.rpm | cpio -id
# dnf install /mnt/haproxy-2.4.22-3.el9_3.x86_64.rpm -y
# mv /etc/haproxy/haproxy.cfg /mnt/
负载调度:
# vim /mnt/haproxy.cfg
listen web
bind *:80
mode http
balance roundrobin
server web1 web1:80 check
server web2 web2:80 check
容器配置:
# vim docker-compose.yml
services:
web1:
image: nginx:latest #使用 nginx 镜像
container_name: web1 # 指定容器名为 web1
restart: always # 容器退出时自动重启
expose:
- 80 # 暴露容器内的 80 端口(仅对 Docker 网络可见)
volumes:
- web1_data:/usr/share/nginx/html # 挂载名为 web1_data 的卷到容器内的 nginx 网页目录
networks:
- mynet1
web2:
image: nginx:latest
container_name: web2
restart: always
expose:
- 80
volumes:
- web2_data:/usr/share/nginx/html
networks:
- mynet1
haproxy:
image: haproxy:2.3 # 使用 HAProxy 2.3 镜像
container_name: haproxy
expose:
- "80"
networks:
- mynet1 # 连接到同一网络
volumes:
- /mnt/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
ports:
- "80:80" # 将宿主机的 80 端口映射到容器的 80 端口(允许外部访问)
networks:
mynet1:
driver: bridge # 使用 bridge 网络驱动(默认)
volumes:
web1_data:
name: web1_data # 显式命名卷为 web1_data
web2_data:
name: web2_data
# docker compose config 【检测语法】
# sudo lsof -i :80 【无输出,确认80端口无占用】
# docker compose -f docker-compose.yml up -d
# docker compose ps 查看运行:
# curl -v http://localhost 查看结果:
# echo "Web1" > /var/lib/docker/volumes/web1_data/_data/index.html
# echo "Web2" > /var/lib/docker/volumes/web2_data/_data/index.html
# for i in {1..4}; do curl -s http://localhost; don
更多推荐
所有评论(0)