Docker 容器技术入门与实践 (四):Docker存储与网络

张开发
2026/4/21 22:22:18 15 分钟阅读

分享文章

Docker 容器技术入门与实践 (四):Docker存储与网络
Docker存储与网络引言在前三篇中我们探讨了Docker的基本概念、安装配置、镜像管理和容器操作。本篇将聚焦于Docker技术栈中至关重要的两个支柱存储和网络。理解Docker如何管理容器内的数据持久化和网络通信是构建稳定、可扩展容器化应用的基础。我们将结合OpenEuler操作系统通过理论讲解、代码示例、功能剖析和日常实践案例深入解析Docker存储与网络的机制、配置方法和最佳实践。第一部分Docker存储容器默认采用隔离的文件系统。当容器停止或删除时其内部由镜像提供的文件层以及运行时产生的数据除非显式保存都会丢失。这种设计有利于保证环境的一致性但对于需要持久化保存的数据如数据库文件、应用日志、配置文件或需要在容器间共享的数据就需要Docker提供的存储机制来解决。1. Docker存储驱动与联合文件系统联合文件系统UnionFSDocker镜像和容器文件系统的基石。它允许将多个目录称为分支或层透明地叠加挂载到同一个目录下。底层通常是只读的如基础镜像层顶层是可读写的容器层。对文件的修改发生在顶层写时复制CoW不影响底层。存储驱动Storage DriverDocker使用存储驱动来管理和实现联合文件系统。不同的驱动有不同的实现方式和性能特点。在OpenEuler上常见的驱动有overlay2目前默认推荐且性能较好的驱动支持多层镜像。devicemapper在早期CentOS/RHEL系统中常用但在OpenEuler上overlay2通常是更好的选择。btrfs如果OpenEuler的根文件系统是Btrfs可以使用此驱动需要btrfs工具。vfs简单但性能差主要用于测试。查看和设置存储驱动查看当前驱动docker info | grep Storage Driver配置驱动通常在/etc/docker/daemon.json中设置若文件不存在则创建{ storage-driver: overlay2 }修改后重启Docker服务sudo systemctl restart docker2. 数据卷Volumes数据卷是Docker推荐的持久化数据的方式。它们由Docker管理独立于容器的生命周期存储在宿主机文件系统通常是/var/lib/docker/volumes/的一个特定区域。核心优势持久化卷中的数据在容器删除后仍然存在。解耦数据存储与容器逻辑分离。共享可以在多个容器间安全地共享数据卷。高效绕过存储驱动直接读写宿主机文件系统性能更好。备份/迁移卷可以方便地备份、恢复或迁移。管理命令创建卷docker volume create my_volume # 创建名为my_volume的卷列出卷docker volume ls查看卷详情docker volume inspect my_volume删除卷docker volume rm my_volume # 删除指定卷 docker volume prune # 删除所有未被使用的卷在容器中使用卷-v或--volume标志# 将卷挂载到容器内的/app/data目录 docker run -d --name my_container -v my_volume:/app/data my_image # 创建匿名卷并挂载 (不推荐不易管理) docker run -d --name my_container -v /app/data my_image--mount标志语法更清晰功能更丰富docker run -d --name my_container \ --mount typevolume,sourcemy_volume,target/app/data my_image文件/目录挂载虽然-v也能挂载宿主机目录-v /host/path:/container/path但严格来说这不属于卷管理而是绑定挂载Bind Mounts。卷是Docker管理的绑定挂载依赖于宿主机的目录结构。权限问题容器内进程访问卷目录的权限取决于容器内进程的UID/GID和宿主机目录的权限。如果宿主机目录权限严格如属主为root可能导致容器内普通用户进程无法写入。解决方法调整宿主机目录权限需谨慎。在Dockerfile中使用USER指令运行特定用户并确保该用户在宿主机目录有权限。在docker run时使用-u指定UID/GID。使用命名卷时Docker通常会自动处理权限但具体行为可能因驱动而异。3. 绑定挂载Bind Mounts绑定挂载直接将宿主机的文件或目录挂载到容器中。它非常灵活但将容器与宿主机文件系统紧密耦合。特点直接映射宿主机路径 - 容器路径。性能好直接访问宿主机文件系统。依赖宿主机路径必须在宿主机存在容器移植性差。权限敏感权限问题比卷更突出直接使用宿主机的权限设置。使用方式# 使用 -v docker run -d --name my_container -v /host/data:/container/data my_image # 使用 --mount docker run -d --name my_container \ --mount typebind,source/host/data,target/container/data my_image应用场景开发时挂载源代码目录到容器实现代码热更新。挂载宿主机配置文件到容器。挂载特定设备文件如/dev/sda1需额外权限。需要直接读写宿主机已知路径的场景。4. 临时文件系统tmpfs mountstmpfs挂载将内存中的临时文件系统挂载到容器中。数据完全存储在内存中速度快但容器停止后数据即丢失。特点内存存储读写速度极快。非持久化容器停止即消失。容量限制可以设置大小限制--tmpfs-size。使用方式# 使用 --tmpfs docker run -d --name my_container --tmpfs /app/tmp my_image # 使用 --mount docker run -d --name my_container \ --mount typetmpfs,destination/app/tmp my_image应用场景存放不需要持久化的临时文件或缓存。对IO速度要求极高的临时数据处理。5. 存储实践案例案例1MySQL数据库持久化# 创建专用卷 docker volume create mysql_data # 运行MySQL容器将数据目录挂载到卷 docker run -d --name mysql_db \ -e MYSQL_ROOT_PASSWORDmysecret \ -v mysql_data:/var/lib/mysql \ mysql:latest # 即使删除容器数据仍在mysql_data卷中。重新创建容器挂载同一卷即可恢复数据。案例2开发环境代码热加载# 假设项目在宿主机的/home/user/project docker run -d --name dev_env \ -v /home/user/project:/app \ -p 8080:8080 \ my_dev_image # 在宿主机修改代码容器内应用即时生效需应用支持热加载。案例3多容器共享配置文件# 创建一个卷存放公共配置 docker volume create app_config # 将配置文件放入卷 (需要先挂载到一个临时容器或使用docker cp) docker run --rm -v app_config:/config alpine cp /path/to/local/config.conf /config/ # 多个容器挂载同一个配置卷 docker run -d --name service1 --mount sourceapp_config,target/etc/app_config my_image1 docker run -d --name service2 --mount sourceapp_config,target/etc/app_config my_image2第二部分Docker网络容器需要与外部世界其他容器、宿主机、互联网进行通信。Docker提供了强大的网络功能来满足不同的连接需求。1. Docker网络驱动Docker通过可插拔的网络驱动实现不同的网络模型。bridge默认网络驱动。创建一个名为docker0的虚拟网桥在OpenEuler上可使用ip addr show docker0查看。每个加入该网络的容器会获得一个虚拟网卡veth pair一端在容器内一端连接到网桥。容器通过网桥进行通信并可通过NAT访问外部网络。这是最常用的模式适用于单主机上的容器间通信。host容器直接使用宿主机的网络命名空间Namespace共享宿主机的网络栈IP地址、端口等。性能最好无NAT开销但牺牲了网络隔离性端口冲突风险。none容器拥有独立的网络命名空间但不配置任何网络接口只有loopback。容器完全隔离需要用户手动配置网络通常结合其他工具使用。overlay用于跨多个Docker宿主机构建容器网络是Docker Swarm集群模式的基础。它使用VXLAN等技术实现跨主机容器间的二层通信。macvlan为容器分配一个独立的MAC地址使其在网络中看起来像是一个物理设备。容器可以直接连接到物理网络需要交换机支持获得一个与宿主机同网段的IP地址。适用于需要容器获得真实IP地址的场景。ipvlan类似于macvlan但容器共享宿主机的MAC地址使用不同的IP地址L2模式或路由L3模式。在某些网络策略下比macvlan更灵活。2. Docker网络模型容器网络命名空间每个容器在创建时除非使用--networkhost或--networkcontainer:id会获得一个独立的网络命名空间包含自己的网络接口、路由表、防火墙规则等。docker0网桥在bridge模式下宿主机上的虚拟网桥。它连接着所有属于默认bridge网络的容器。veth pair虚拟以太网设备对。一端vethX在宿主机的命名空间连接到docker0网桥另一端eth0在容器的命名空间内。NAT (SNAT/DNAT)默认情况下容器通过docker0网桥访问外部网络时源IPContainer IP会被SNAT源地址转换为宿主机的IP。当外部访问映射到容器的端口时-p 80:8080会使用DNAT目的地址转换将目标IP和端口转换为容器的IP和端口。3. 网络管理命令列出网络docker network ls查看网络详情docker network inspect bridge # 查看默认bridge网络详情创建网络docker network create my_network # 创建一个新的bridge网络 docker network create -d macvlan --subnet192.168.1.0/24 --gateway192.168.1.1 -o parenteth0 my_macvlan_net # 创建macvlan网络删除网络docker network rm my_network # 删除网络需无容器连接 docker network prune # 删除所有未被使用的网络将容器连接到网络docker run -d --name container1 --network my_network my_image # 启动时连接 docker network connect my_network existing_container # 连接已运行容器断开容器与网络的连接docker network disconnect my_network existing_container4. 端口发布Port Publishing为了让外部网络宿主机外部能够访问容器内部的服务需要将容器内部的端口映射发布到宿主机的端口上。-p或--publish标志# 将容器80端口映射到宿主机8080端口 (TCP默认) docker run -d -p 8080:80 nginx # 映射UDP端口 docker run -d -p 8080:80/udp my_udp_service # 映射多个端口 docker run -d -p 8080:80 -p 8443:443 nginx # 让Docker自动分配宿主机端口 (查看用docker ps或docker port) docker run -d -p 80 nginx查看端口映射docker port container_name # 查看指定容器的端口映射 docker ps # 查看PORTS列5. 容器间通信同一网络内Docker为同一网络内的容器提供了基于容器名称或使用--name指定的别名的DNS解析服务。容器间可以直接通过容器名进行通信无需知道对方的IP地址。docker network create app_net docker run -d --name web --network app_net nginx docker run -it --name client --network app_net alpine / # ping web # 在client容器内ping web容器成功 / # wget -O- http://web # 访问web容器的nginx不同网络默认情况下不同网络的容器无法直接通信除非通过宿主机路由或额外配置。需要将容器连接到同一个网络或者配置网络路由规则。6. 网络实践案例案例1Web应用栈 (Nginx PHP-FPM MySQL)# 创建专用网络 docker network create web_app_net # 运行MySQL (使用卷持久化) docker run -d --name mysql --network web_app_net -v mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORDpass mysql # 运行PHP-FPM (挂载应用代码) docker run -d --name php-fpm --network web_app_net -v $(pwd)/app:/var/www/html php:fpm # 运行Nginx (挂载代码和配置发布端口) docker run -d --name nginx --network web_app_net -v $(pwd)/app:/var/www/html -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf -p 80:80 nginx # 在app目录放入PHP代码。Nginx配置中设置fastcgi_pass php-fpm:9000; 容器间通过名称php-fpm通信。案例2使用host网络提升性能docker run -d --name high_perf_app --network host my_image # 容器直接使用宿主机网络 # 注意容器内应用监听端口时会直接占用宿主机的端口可能导致冲突。案例3macvlan给容器真实IP# 假设宿主机eth0在192.168.1.0/24网段网关192.168.1.1 docker network create -d macvlan --subnet192.168.1.0/24 --gateway192.168.1.1 -o parenteth0 macvlan_net docker run -d --name container_with_ip --network macvlan_net my_image # 容器将获得一个192.168.1.0/24网段的独立IP可与同网段其他物理设备直接通信。案例4Docker Compose定义网络与存储 (简化上述Web栈)version: 3.8 services: mysql: image: mysql:latest volumes: - mysql_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: pass networks: - app_net php-fpm: image: php:fpm volumes: - ./app:/var/www/html networks: - app_net nginx: image: nginx:latest volumes: - ./app:/var/www/html - ./nginx.conf:/etc/nginx/nginx.conf ports: - 80:80 networks: - app_net volumes: mysql_data: networks: app_net: driver: bridge运行docker-compose up -dOpenEuler系统注意事项防火墙OpenEuler默认使用firewalld。Docker在安装时通常会添加dockerzone并开放必要的规则。如果遇到网络问题如端口映射后无法访问检查firewalld状态和规则sudo systemctl status firewalld sudo firewall-cmd --list-all --zonedocker # 查看docker zone规则 sudo firewall-cmd --add-port80/tcp --permanent --zonepublic # 如果需要额外开放端口到public zone sudo firewall-cmd --reloadSELinuxOpenEuler可能启用SELinux。如果使用绑定挂载出现权限问题即使文件权限正确可能是SELinux安全上下文导致。可以尝试临时禁用SELinux生产环境不推荐setenforce 0添加正确的SELinux标签使用chcon或semanage fcontext。在docker run时使用--security-opt labeldisable禁用SELinux保护有安全风险。使用卷代替绑定挂载卷通常不受此问题影响。网络性能对于高性能网络需求如HPC、金融交易考虑使用host网络、macvlan/ipvlan或高级网络驱动如SR-IOV并优化OpenEuler内核参数如调整net.core.somaxconn,net.ipv4.tcp_tw_reuse等。测试工具可使用iperf3。总结Docker的存储和网络机制为容器化应用提供了灵活、可靠的数据管理和通信能力。在OpenEuler系统上存储优先使用数据卷进行持久化存储管理。理解overlay2驱动原理。掌握volume、bind mount、tmpfs的适用场景和权限管理。结合docker volume命令和Compose文件进行管理。网络掌握bridge、host、none、macvlan等核心网络模式及其工作原理。熟练使用docker network命令创建和管理网络。理解容器间通过容器名称在同一网络内通信的便利性。熟练使用端口发布-p。在OpenEuler上注意firewalld和SELinux对网络和存储访问的影响。通过本篇的学习和实践您应该能够为容器应用配置合适的持久化存储方案并构建满足不同需求的容器网络拓扑为在OpenEuler上部署和管理复杂的容器化服务打下坚实基础。在后续篇章中我们将探讨Docker Compose、Docker Swarm/Kubernetes集群管理等更高级的主题。

更多文章