容器基础知识
Iaas Paas Saas(了解)
Iaas(基础设施即服务):基于云的服务,按需付费,用于存储,网络和虚拟化等服务
Paas(平台即服务):Internet上可用的硬件和软件工具
Saas(软件即服务):可通过互联网通过第三方获得的软件

容器介绍⭐⭐
- 容器是一种轻量级虚拟化技术,它将应用程序及其依赖项打包成一个可移植的镜像,然后将其隔离运行在自己的进程中,以实现资源的隔离和限制
- 容器是隔离的环境中运行的一个进程,如果进程结束,容器就会停止
- 容器的隔离环境:相当于一个mini的系统,拥有自己的ip地址,系统文件,主机名,进程管理
容器vs虚拟机⭐⭐
| 特性 | 容器 | 虚拟机 |
| 资源利用率 | 高(多个容器共享操作系统内核) | 低(每个虚拟机都有独立的操作系统) |
| 启动速度 | 启动速度非常快 | 启动数据较慢 |
| 隔离性 | 隔离性较低,适用于轻量级应用 | 隔离性较高,适合运行不同操作系统的应用 |
| 性能 | 较高(共享内核和资源) | 稍低(虚拟化层和操作系统的开销) |
| 管理和部署 | 简单,使用容器化工具(docker) | 较复杂需要虚拟化管理程序(VMware,KVM) |
| 可移植性 | 非常好,容器可以在任何支持容器的平台上运行 | 一般,虚拟机迁移需要相应的平台支持 |
| 安全性 | 相对较低,若容器间存在漏洞,风险可能增加 | 较高,由于独立的虚拟环境,隔离性更强 |
| 应用场景 | 适合微服务、快速开发和部署的场景 | 适合需要完整操作系统功能的应用,如企业环境等 |
Hypervisor(虚拟机监控器):允许在同一物理主机上运行多个操作系统和应用程序

docker环境构建⭐⭐
linux内核:3.10以上(如果是旧版本内核需要升级内核)
| docker环境 | ip | 配置 |
| docker01 | 10.0.0.81/172.16.1.81 | 2c4G(至少1c2G) |
| docker02 | 10.0.0.82/172.16.1.82 | 2c4G(至少1c2G) |
docker-ce介绍⭐⭐
docker-ce 是 Docker 社区版软件包,安装后就会提供 docker 命令行工具和完整的容器运行环境
安装 docker-ce 时会自动安装以下组件:
| 组件名称 | 功能说明 |
|---|---|
docker |
Docker 客户端命令行工具 |
dockerd |
Docker 守护进程(服务端) |
containerd |
容器运行时(Docker 依赖的核心组件) |
runc |
容器执行引擎 |
| Docker 相关配置文件 | 服务配置、镜像存储配置等 |
docker的安装⭐⭐
# 设置docker官方仓库(dnf是新一代的rpm包管理工具) # 安装依赖工具 sudo dnf -y install dnf-plugins-core # dnf-plugins-core,提供dnf config-manager命令,用于管理仓库配置 # 添加docker官方仓库 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 将docker的官方yum仓库配置添加到系统中,后续可以通过dnf install安装docker # 该命令会在 /etc/yum.repos.d/ 下生成 docker-ce.repo 文件 # 安装docker-ce dnf -y install docker-ce # 启动docker服务 sudo systemctl enable --now docker # enable:设置docker开机自启动 # --now:立即启动服务(无需重启系统) # 下载docker自动补全包 yum install -y bash-completion bash-completion-extras
安装/卸载二进制docker环境
# 安装二进制docker环境 # 安装二进制包 [root@harbor ~]# wget https://download.docker.com/linux/static/stable/x86_64/docker-27.0.3.tgz [root@harbor ~]# tar xf docker-27.0.3.tgz # 将二进制文件复制到PATH变量 [root@harbor ~]# cp /root/docker/* /usr/bin/ # 启动docker [root@harbor ~]# dockerd # 查看docker版本号 [root@harbor ~]# docker version # 卸载二进制的docker环境 # 停止服务 [root@harbor ~]# pkill dockerd # 卸载docker相关程序(卸载完成可以查看docker版本进行验证) [root@harbor ~]# ls /root/docker containerd containerd-shim-runc-v2 ctr docker dockerd docker-init docker-proxy runc [root@harbor ~]# for i in `ls docker`;do rm -rf /usr/bin/$i;done
docker下载镜像加速

https://github.com/DaoCloud/public-image-mirror?tab=readme-ov-file#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95 [root@docker02 ~]# cat /etc/docker/daemon.json { "registry-mirrors": [ "https://docker.m.daocloud.io" ] }
快速构建docker

| docker相关词汇 | 说明 |
| 镜像 | 存放各种环境或服务 |
| 容器 | 镜像的运行实例(进程) |
| 仓库(存放镜像) | 远程仓库、本地仓库 |
docker run -d -p 80:80 nginx # 创建并启动一个新容器 # -d 容器后台运行 # -p 80:80 端口映射,第一个是宿主机端口,第二个是容器内部端口 将主机的80端口映射到容器的80端口(所有访问主机80端口的流量,都会自动转发到容器的80端口) # nginx 镜像名字 docker客户端找dockerd服务端,查询是否有nginx镜像 如果有,则启动这个镜像(如果没有,则下载该镜像并启动) 创建一个隔离的容器环境,映射主机80端口到容器80端口,并在后台启动该服务 # net.ipv4.ip_forward = 1 Linux内核参数,控制是否允许ip数据包转发 docker依赖此功能实现容器与外部网络的通信 [root@docker01 ~]# tail -1 /etc/sysctl.conf net.ipv4.ip_forward = 1 [root@docker01 ~]# sysctl -p
# 重新加载/etc/sysctl.conf文件中的内核参数,使修改后的配置立即生效,无需重启系统 net.ipv4.ip_forward = 1
docker镜像管理、docker容器管理、端口映射、数据卷挂载⭐⭐⭐⭐⭐
docker镜像管理⭐⭐⭐⭐⭐
docker images === docker image ls # 查看镜像列表 docker search # 搜索镜像:用于在Docker Hub或其他注册表中搜索镜像(也可以直接访问hub.docker.com进行搜索镜像) docker [image] pull 镜像 # 下载镜像到本地仓库 # 如果本地仓库有则提示镜像已下载 # 如果本地进行仓库没有,则docker服务端访问远程仓库,下载镜像到本地仓库 docker [image] push 镜像 # 上传镜像到仓库(未来主要用于自建docker仓库) docker [image] save # 导出镜像 docker save nginx:alpine -o /root/nginx_alpine.tar # 保存docker镜像到指定的文件 # 将docker镜像传输到其他节点 docker image save nginx:alpine |ssh root@10.0.0.82 "docker load" docker [image] load # 导入镜像 docker load -i /root/nginx:alpine.tar docker rmi 镜像 === docker image rm 镜像 删除镜像(如果创建了该镜像的容器,需要先删除该容器) docker image prune # 用于清理悬空镜像 悬空镜像(Dangling Images):没有标签、没有被任何容器引用、但仍占用磁盘空间的镜像 docker [image] tag 镜像 # 给镜像设置标签 [root@docker01 ~]# docker image tag nginx:alpine nginx:alpine-yuanxiaojiang [root@docker01 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx alpine 77656422f700 5 days ago 52.5MB nginx alpine-yuanxiaojiang 77656422f700 5 days ago 52.5MB docker image inspect 镜像 # 查看镜像的详细信息(输出的是json格式) json数据可以通过jq命令获取 docker image inspect nginx:alpine |jq .[0].Id docker [image] build # 自定义镜像
docker容器管理⭐⭐⭐⭐⭐
/var/lib/docker/ docker默认数据存储根目录
docker [container] ps # 查看容器列表 -a:查看所有容器 -q:只显示id
docker [container] run # 创建并运行容器 -d:后台运行,返回容器id --name:为容器命名 --rm:当容器停止运行后,自动删除该容器 -v:挂载数据卷
-e:设置容器内的环境变量 -it:交互模式运行(容器退出则自动关闭容器,并不会删除容器) -i(--interactive):保持标准输入,允许用户与容器内的进程交互 -t(--try):分配一个伪终端(使用命令行解释器/bin/bash或/bin/sh)
--restart:容器重启策略
no:不自动重启容器,容器退出后就保持停止状态
on-failure[:max-retries]:只在容器异常退出(非0状态)时自动重启,可限制最大重试次数
always:无论容器如何退出(除非手动停止),都会无条件自动重启
unless-stopped:总是自动重启,除非用户显示停止容器,否者即使宿主机重启也会恢复运行 docker run 背后涉及的命令 查找本地是否有这个镜像,如果没有则先下载镜像. docker image pull 下载完成 创建容器 docker container create 启动容器docker container start
docker [container] exec/attach 正在运行的容器 docker [container] exec 正在运行的容器 # 用于与运行中的容器进行交互 连接的时候需要使用-it创建终端 多个独立会话互不干扰(一个容器允许多个会话同时操控) docker [container] attach 正在运行的容器 # 用于与运行中的容器进行交互 容器自身需要内嵌命令行解释器 多个会话共享相同的输入输出流(一个容器只允许一个会话操控)
docker [container] cp 源路径或文件 目标路径或文件 -a:表示文件的属性不变(uid gid) docker cp nginx_alpine_docker:/usr/share/nginx/html/index.html /tmp # 容器-->宿主机 docker cp /tmp/index nginx_alpine_docker:/usr/share/nginx/html/index.html # 宿主机-->容器 docker [container] stats/top/inspect docker [container] stats # 查看所有运行中的容器的状态,如果要看所有加上-a选项 docker container top # 查看某个容器的进程信息 docker container inspect # 显示某个容器的详细信息 docker [container] create/start/restart/stop/kill/rm docker [container] rm # 删除容器 -f:强制删除 docker stop 关闭容器 # 关闭容器:向容器中的主进程发出信号(kill) socker [container] kill # 强制终止容器运行(并不会删除容器)
docker [container] commit 源容器 新镜像名 # 根据容器生成镜像
案例:运行一个数据库容器并登录
docker run -d --name "my_mysql" -e MYSQL_ROOT_PASSWORD=root mysql:latest -e:设置容器内的环境变量 docker exec -it my_mysql /bin/bash mysql -uroot -p docker exec -it my_mysql mysql -uroot -p
案例:临时运行一个容器并获取系统信息
docker run --rm nginx:stable cat /etc/os-release --rm:当容器停止运行后,自动删除这个容器 为什么容器会退出: docker容器的存活时间完全依赖主进程(即cat /etc/os-release) 当cat命令执行完毕后,主进程结束,容器自动退出
案例:进入并修改已运行nginx容器中的首页内容⭐⭐
# 查看 Nginx 官方镜像的文档获取文件位置 默认网页目录:/usr/share/nginx/html/ 配置文件目录:/etc/nginx/nginx.conf 和 /etc/nginx/conf.d/ # 如果没有运行中的容器则创建 docker run -d -p 80:80 --name "nginx_alpine_docker" nginx:alpine # 进入运行中的容器 docker exec -it nginx_alpine_docker /bin/sh # 修改nginx首页内容 echo nginx_alpine_docker >/usr/share/nginx/html/index.html
端口映射⭐⭐⭐
Docker 端口映射即映射容器内应用的服务端口到本机宿主机器
开启内核转发功能
net.ipv4.ip_forward = 1 #Linux内核参数,控制是否允许ip数据包转发 docker依赖此功能实现容器与外部网络的通信
端口映射核心机制:iptables NAT 规则
当执行 docker run -p 8000:80 时,Docker 会通过 iptables 在 NAT 表(网络地址转换表)中添加规则,将宿主机的8000端口流量转发到容器的 80 端口
[root@docker01 ~]# docker run -d -p 8000:80 --name 'nginx_apline_docker' nginx:alpine [root@docker01 ~]# docker ps |grep 8000 b6a2d501ab17 nginx:alpine "/docker-entrypoint.…" 12 minutes ago Up 12 minutes 0.0.0.0:8000->80/tcp, :::8000->80/tcp nginx_apline_docker [root@docker01 ~]# sudo iptables -t nat -L -n -v Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 # 如果流量来自 docker0 网卡(即容器之间的通信),直接返回上级链,不进行端口映射 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8000 to:172.17.0.2:80 # 将宿主机的 8000 端口流量转发到容器的 80 端口

端口映射⭐⭐⭐
| docker run | 示例 |
| -p(小写字母p) 宿主机的端口:容器中的端口 | -p 80:80 -p 443:443 |
| -p :容器中的端口 | -p :80 表示宿主机端口随机(很少用) |
| -p 端口范围:端口范围 | -p 80-88:80-88 |
[root@docker01 ~]# docker run -d -p 8080:8080 -p 8081:8081 nginx:alpine [root@docker01 ~]# docker port cranky_williamson 8080/tcp -> 0.0.0.0:8080 8080/tcp -> [::]:8080 8081/tcp -> 0.0.0.0:8081 8081/tcp -> [::]:8081
ip绑定端口
显示用户只能通过宿主机的某个网卡连接这个端口
docker run -d --name 'nginx_alpine_bind_ip' -p 172.16.1.81:12306:80 nginx:alpine
数据卷挂载(docker run -v 宿主机路径:容器内部路径)⭐⭐⭐⭐⭐

- 删除限制:docker volume prune -f 仅能删除未被任何容器(包括已停止的)使用的存储卷
- 自动创建:启动容器时,如果指定的存储卷不存在,Docker 会自动创建它
- 匿名卷:运行容器时不显式指定存储卷,Docker 会随机生成一个匿名存储卷
- 初始化拷贝:当新卷挂载到非空容器目录时,容器目录的现有数据会被拷贝到存储卷中
- 数据覆盖:当已存在的存储卷挂载到容器目录时,存储卷的内容会完全覆盖容器挂载点的内容
- 查看挂载:使用 docker container inspect <容器名/ID> 命令可以查看已运行容器的详细挂载信息
文件inode与容器挂载(了解)⭐
vi/vim/sed -i这些编辑器修改文件时,实际上时创建新文件然后重名名,所以文件的inode号会改变
docker绑定挂载时基于inode号建立的,inode号改变,容器内的挂载点就会断开连接
- 测试环境
# 运行一个nginx并挂载一个inde文件 [root@docker01 ~]# mkdir -p /app/docker/code/nginx [root@docker01 ~]# echo docker01.linux.cn_data_volumne >/app/docker/code/nginx/index.html [root@docker01 ~]# docker run -d --name "docker_volumnt_nginx_v1" -p 80:80 \ -v /app/docker/code/nginx/index.html:/usr/share/nginx/html/index.html nginx:alpine # 查看容器挂载的数据卷 [root@docker01 docker]# docker inspect docker_volumnt_nginx_v1 |jq .[].HostConfig.Binds ["/app/docker/code/index.html:/usr/share/nginx/html/index.html"] # vim或sed修改index.html后,重新访问index,页面内容没有发生变化
- 解决方案
# 方案1:使用不会改变 inode 的编辑方式 # 使用追加方式(不改变inode) echo "new content" >> /app/docker/code/index.html # 使用重定向(会改变inode),需要重启容器 echo "new content" > /app/docker/code/index.html docker restart docker_volumnt_nginx_v1 # 方案2:重启容器重新建立挂载 docker restart docker_volumnt_nginx_v1 # 方案3:使用目录挂载代替文件挂载(推荐) docker run -d --name nginx_dir_mount -p 81:80 \ -v /app/docker/code/:/usr/share/nginx/html/ nginx:alpine
案例:将宿主机的nginx配置文件和代码目录挂载到容器⭐⭐⭐
nginx:alpine 镜像 子配置文件:/app/docker/conf/nginx/conf.d/ --> /etc/nginx/conf.d/ 主配置文件:/app/docker/conf/nginx/nginx.conf --> /etc/nginx/nginx.conf 站点目录:/app/docker/code/nginx/ --> /app/code/nginx/ [root@docker01 ~]# mkdir -p /app/docker/code/nginx /app/docker/conf/nginx/conf.d/ [root@docker01 ~]# echo docker01.linux.cn_data_volumne >/app/docker/code/nginx/index.html [root@docker01 ~]# vim /app/docker/conf/nginx/conf.d/docker01.linux.cn.conf server{ listen 80; server_name docker01.linux.cn; root /app/code/nginx; location / { index index.html; } } [root@docker01 ~]# docker run -d --name "nginx_alpine_pull_nginx_data" -p 80:80 nginx:alpine [root@docker01 ~]# docker cp nginx_alpine_pull_nginx_data:/etc/nginx/nginx.conf /app/docker/conf/nginx/ [root@docker01 ~]# docker rm -f nginx_alpine_pull_nginx_data [root@docker01 ~]# docker run -d --name "nginx_alpine_docker_volume" -p 80:80 \ -v /app/docker/conf/nginx/conf.d/:/etc/nginx/conf.d/ \ -v /app/docker/conf/nginx/nginx.conf:/etc/nginx/nginx.conf \ -v /app/docker/code/nginx:/app/code/nginx/ \
# 容器中如果没有/app/code/nginx/文件则自动创建
# 此处没有使用了目录挂载,所以修改index.html时不会断开挂载 --restart=always nginx:alpine
创建数据卷空间⭐⭐⭐⭐⭐
只关注容器中的数据不丢,不关注数据具体存放位置
/var/lib/docker/ docker默认数据存储根目录
# 创建数据卷 [root@docker01 ~]# docker volume create volume_nginxlogdata # 查看数据卷 [root@docker01 ~]# docker volume ls DRIVER VOLUME NAME local volume_nginxlogdata [root@docker01 ~]# tree /var/lib/docker/volumes/volume_nginxlogdata/ /var/lib/docker/volumes/volume_nginxlogdata/ └── _data # 挂载数据卷 [root@docker01 ~]# docker run -d --name "nginx_alpine_volume_data" -p 81:80 \ -v volume_nginxlogdata:/var/log/nginx nginx:alpine [root@docker01 ~]# tree /var/lib/docker/volumes/volume_nginxlogdata/ /var/lib/docker/volumes/volume_nginxlogdata/ └── _data ├── access.log -> /dev/stdout └── error.log -> /dev/stderr 在 Docker 环境中,Nginx 容器的日志默认会输出到 标准输出(stdout) 和 标准错误输出(stderr), 而不是像传统部署那样将日志写入到容器内的 /var/log/nginx/access.log 或 /var/log/nginx/error.log 文件中 # 删除数据卷 docker volume rm 数据卷名 删除指定的一个或多个数据卷 docker volume prune 删除所有未被容器使用的数据卷(容器已被删除但数据卷未被删除、创建后未被使用的数据卷) # 查看日志 docker logs 容器id或容器名
容器挂载指定权限⭐⭐
# 容器c1: 默认挂载(隐式读写权限) docker run -d --name c1 -v /linux92/:/usr/share/nginx/html nginx:alpine # 容器c2: 显式指定读写权限 docker run -d --name c2 -v /linux92/:/usr/share/nginx/html:rw nginx:alpine # 容器c3: 指定只读权限 docker run -d --name c3 -v /linux92/:/usr/share/nginx/html:ro nginx:alpine # 容器c1(默认rw权限):创建文件成功 root@docker102:~# docker exec c1 touch /usr/share/nginx/html/c1.log # 容器c2(显式rw权限):创建文件成功 root@docker102:~# docker exec c2 touch /usr/share/nginx/html/c2.log # 容器c3(ro只读权限):创建文件失败 root@docker102:~# docker exec c3 touch /usr/share/nginx/html/c3.log
运行的容器未持久化存储⭐⭐⭐
# 项目背景:docker容器运行一段时间,发现没有做数据持久化 # 解决步骤 1.确认应用程序将数据存放容器哪个目录(确认容器内的数据目录) 2.创建宿主机持久化目录 3.在线备份数据到宿主机 通过docker cp命令,在不停之当前运行容器的情况下,将数据拷贝出来 此时宿主机目录中存放了执行docker cp命令这一时刻的所有数据 4.停止并删除旧容器 5.以持久化方式启动新容器 # 如何确保备份后到重启前新数据不丢失 方案A:短暂停机窗口(适用于可容忍秒级中断的应用) 方案B:双重备份(适用于要求数据强一致性的应用,如数据库)
浙公网安备 33010602011771号