yuanxiaojiang
人的放纵是本能,自律才是修行

容器基础知识

  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:双重备份(适用于要求数据强一致性的应用,如数据库)

 

posted on 2025-04-12 09:59  猿小姜  阅读(19)  评论(0)    收藏  举报

levels of contents