Docker基础入门

Docker的基础使用

Docker的安装

不同的Linux发行版中Docker的安装方式略有不同:

安装docker之前需要确保已配置可用的yum镜像源,参照:CentOS的YUM源配置

Uninstall old versions

shell
yum remove docker docker-client docker-client-latest docker-common docker-latest \
           docker-latest-logrotate docker-logrotate docker-engine

install using the repository :

shell
yum install -y yum-utils

#Set up the repository    `ls /etc/yum.repos.d/`
yum-config-manager --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
# centos7 install
yum makecache fast && yum install -y docker-ce docker-ce-cli containerd.io 
# rocky8 install
yum install -y docker-ce --allowerasing

#start
systemctl start docker && systemctl enable docker

docker version

安装指定版本docker

找到所有可用docker版本列表

bash
yum list docker-ce --showduplicates | sort -r

安装指定版本,用上面的版本号替换<VERSION_STRING>

text
yum install docker-ce-<VERSION_STRING>.x86_64 docker-ce-cli-<VERSION_STRING>.x86_64 containerd.io

例如:

bash
yum install docker-ce-3:20.10.5-3.el7.x86_64 docker-ce-cli-3:20.10.5-3.el7.x86_64 containerd.io

注意加上 .x86_64 大版本号

Ubuntu 参照 docker 官网安装教程:https://docs.docker.com/engine/install/ubuntu/

在 Ubuntu 24 中安装 Docker 的详细步骤:

1. 安装依赖包

bash
sudo apt update
sudo apt install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common \
    gnupg \
    lsb-release

2. 添加 Docker 的 GPG 密钥

bash
# 创建必要的目录
sudo install -m 0755 -d /etc/apt/keyrings

# 下载并添加阿里云镜像的 GPG 密钥
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

3. 添加 Docker 的 APT 软件源

添加阿里云镜像源:

bash
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

4. 更新软件包列表

bash
sudo apt update

5. 安装 Docker CE

bash
sudo apt install -y \
    docker-ce \
    docker-ce-cli \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin

6. 启动并启用 Docker 服务

bash
sudo systemctl start docker && sudo systemctl enable docker

7. 验证安装

bash
docker --version
docker info

Ubuntu通常不使用root用户,所以很多命令都需要加sudo来执行,为了方便使用docker命令,建议将当前用户加入docker用户组:

bash
sudo usermod -aG docker $USER

执行命令后需要重启Ubuntu才能生效


配置镜像加速

  1. 配置代理的方式(本机使用Clash并开启LAN):Docker 配置代理,编辑代理配置文件:
bash
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf

# 添加下面内容(clash)
[Service]
Environment="HTTP_PROXY=http://192.168.43.62:7897"
Environment="HTTPS_PROXY=http://192.168.43.62:7897"
Environment="NO_PROXY=localhost,127.0.0.1,192.168.0.0/16,172.17.16.0/20"

# 重启Docker
sudo systemctl daemon-reload && sudo systemctl restart docker

v2ray代理的添加:

bash
Environment="HTTP_PROXY=http://192.168.43.62:10808"
Environment="HTTPS_PROXY=http://192.168.43.62:10808"

  1. 在线配置镜像加速(越来越难找到能用的了): 阿里云镜像加速说明
bash
# 确保存在 `/etc/docker` 目录,若不存在先创建:
sudo mkdir -p /etc/docker && sudo touch /etc/docker/daemon.json

sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
        "https://docker.m.daocloud.io",
        "https://docker.1ms.run"
    ],
    "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

配置好后,重启Docker即可:

bash
sudo systemctl daemon-reload && sudo systemctl restart docker

镜像加速网站:毫秒镜像public-image-mirror


其他可能可用的地址:

bash
tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
        "https://dytt.online",
        "https://func.ink",
        "https://docker.linkedbus.com",
        "https://lispy.org",
        "https://rsbud4vc.mirror.aliyuncs.com",
        "https://registry.cn-hangzhou.aliyuncs.com",
        "https://akchsmlh.mirror.aliyuncs.com",
        "https://2epe3hl0.mirror.aliyuncs.com",
        "https://k7wsl2ss.mirror.aliyuncs.com"
    ],
    "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

Docker基础命令

Docker官网—常用命令

shell
docker version
docker info

# 列出所有运行中的容器的资源使用情况(CPU,内存), 
# 默认情况下,docker stats 会持续更新数据,加上--no-stream选项可以只获取一次数据然后退出
docker stats --no-stream

# 查看ocker使用的不同类型的资源所占用的空间
docker system df

docker xxx  --help     # 命令

Docker镜像

Docker镜像是由基础环境+软件构成的 (例如 :redis的完整镜像应该是: linux系统 + redis软件)

bash
# 查看本地主机上的所有镜像
docker images      

# 查看指定镜像的具体信息
docker container inspect 容器名     # 等同于 docker inspect 容器
# 获取容器/镜像的元数据
docker inspect NAME|ID

# 重命名
docker tag 原镜像:标签 新镜像名:标签 
docker tag 860c279d2fec 新镜像名:标签

搜索和下载镜像:

bash
docker search xxx                   # 搜索镜像:如 mysql,redis......
docker search ventixy.us.kg/redis   # 加速搜索

# 下载镜像 默认为最新版本
docker pull xxx                    
docker pull redis                   # 等同于docker pull redis:latest
docker pull mysql:5.7               # 可指定docker官网可查询到的版本

删除镜像:

bash
docker rmi redis:7.4.1
docker rmi -f imageID                    #根据镜像ID删除镜像
docker rmi -f $(docker images -aq)       #删除所有镜像

docker image prune   # 移除游离镜像 dangling:游离镜像(没有镜像名字的)

Docker容器管理

要创建容器,必须先下载镜像。从镜像创建容器,有两个命令:docker run的立即启动,docker create得稍后自己手动启动

shell
docker ps -a                    # 查看运行中的容器(-a查看全部,-q只显示id)
docker top container_id         # 查看指定容器中的进程信息

# 创建一个新的容器并运行一个命令
docker run xxx
# 启动并进入容器(使用exit停止并退出,也可以使用Ctrl+P+Q不停止退出)
docker run -it centos /bin/bash 
#【问题】发现centos停止了!?原因:docker容器使用后台运行必须要有一个前台进程
docker run -d centos            

从镜像创建容器后,后续再次启动需要执行docker start, 停止和重启等参照:

bash
docker start   container_id     #启动容器
docker stop    container_id     #停止正在运行的容器(优雅停机)
docker kill    container_id     #强制停止正在运行的容器(kill是强制kill -9,约等于直接拔电源)
docker restart container_id     #重启容器

删除容器(不能删除正在运行的容器,如需强制删除需添加-f):

bash
docker rm 86fe3bcb173e          # 删除指定id的容器
docker rm -f $(docker ps -aq)   # 删除全部容器

容器内部操作

docker exec :在运行的容器中执行命令

bash
docker exec -it <container ID> /bin/bash      # 进入容器内部

# 以特权方式进入容器 (0表示用户)
docker exec -it -u 0:0 --privileged container_id /bin/bash  

exit             # 退出container (或者使用Ctrl + D)

容器内部操作示例:更改容器内系统的root密码

bash
docker exec -it <MyContainer> bash            # 进入后修改
root@MyContainer:/# passwd
Enter new UNIX password:
Retype new UNIX password:

docker run 命令详解

docker run 用于从镜像创建并启动一个容器。支持多种参数和选项,可以灵活地配置容器的行为

bash
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
  • OPTIONS:配置容器的各种选项。
  • IMAGE:指定要运行的镜像名称或 ID。
  • COMMAND:容器启动后执行的命令(可选)。
  • ARG:传递给命令的参数(可选)。
bash
# 从 `ubuntu` 镜像启动一个容器,执行默认命令后退出
docker run ubuntu  

#  从 `ubuntu` 镜像启动一个容器,执行 `echo "Hello, Docker!"` 后退出    
docker run ubuntu echo "Hello, Docker!"

常用 OPTIONS 参数说明如下:


容器基础信息OPTIONS 参数

选项 描述
--name 为容器指定一个名称(默认随机生成)
-h 指定容器的hostname

容器运行模式

选项 描述
-d--detach 后台运行容器( detached 模式)。
-it 以交互模式运行容器(分配一个伪终端并保持 STDIN 打开)。
--rm 容器退出后自动删除容器。
  1. nginx 镜像启动一个容器,并在后台运行
bash
docker run -d nginx
  1. ubuntu 镜像启动一个容器,并以交互模式运行 Bash
bash
docker run -it ubuntu /bin/bash
  1. ubuntu 镜像启动一个容器,并在容器退出后自动删除
bash
docker run --rm ubuntu

网络和资源限制

  1. 端口映射和网络配置
选项 描述
-p--publish 将容器端口映射到宿主机端口(格式:宿主机端口:容器端口)。
--network 指定容器使用的网络(如 bridgehostnone 或自定义网络)。

nginx 镜像启动一个容器,并将容器的 80 端口映射到宿主机的 8080 端口

bash
docker run -d -p 8080:80 nginx

创建一个自定义网络 my-network,并在该网络中启动一个容器

bash
docker network create my-network
docker run -d --name my-container --network my-network nginx

  1. 容器资源限制
选项 描述
-m--memory 限制容器使用的内存(如 -m 512m 限制为 512MB)。
--cpus 限制容器使用的 CPU 核心数(如 --cpus="1.5" 限制为 1.5 个核心)。

示例:从 ubuntu 镜像启动一个容器,并限制内存为 512MB,CPU 为 1.5 个核心

bash
docker run -m 512m --cpus="1.5" ubuntu

数据卷和文件挂载

在 Docker 中,-v--volume--mount 标志用于将宿主机上的文件或目录挂载到容器中,或者创建数据卷

选项 描述
-v--volume 将宿主机的目录或文件挂载到容器中(格式:宿主机路径:容器路径)。
--mount 更灵活的挂载方式(支持绑定挂载、卷挂载等)。
  1. -v--volume 语法及使用示例
bash
-v [host-src]:[container-dest][:<options>]
  • host-src: 宿主机上的路径(可以是绝对路径或相对路径)或者一个已存在的数据卷名称。
  • container-dest: 容器内的目标路径。
  • options (可选): 可以包括 ro(只读)或 rw(读写,默认值)。

如:/path/on/host:/path/in/container:ro

nginx 镜像启动一个容器,并将宿主机的 /host/data 目录挂载到容器的 /container/data 目录

bash
docker run -d -v /host/data:/container/data nginx

  1. --mount的语法及应用
bash
--mount source=<source>,target=<destination>[,option=value]
  • source: 宿主机上的路径、文件或数据卷名。
  • target: 容器内的路径。
  • options (可选): 包括但不限于 readonly, volume-opt, 等等

示例:将名为 mydata 的数据卷挂载到容器中的 /var/lib/mysql 目录

bash
docker run -d --mount source=mydata,target=/var/lib/mysql --name db mysql:latest

其他常用选项

选项 描述
--restart 设置容器的重启策略(如 --restart always)。默认为 no
--entrypoint 覆盖镜像的默认入口点。默认情况下运行的是 /bin/bash
--user 指定运行容器的用户(如 --user 1000)。默认为 root
--workdir 设置容器的工作目录(如 --workdir /app)。默认是根目录 /

环境变量

选项 描述
-e--env 设置容器的环境变量(如 -e MY_ENV=value)。
--env-file 从文件加载环境变量(每行一个变量)。

ubuntu 镜像启动一个容器,并设置环境变量 MY_ENV=value

bash
docker run -e MY_ENV=value ubuntu

Dcoker数据持久化

Docker 主要提供两种将数据持久化到宿主机的方式:

  1. 命名卷 (Named Volumes):

    • 特点: 由 Docker 创建和管理,并赋予一个明确的名称。存储在宿主机文件系统的一个特定区域(通常是 /var/lib/docker/volumes/ 在 Linux 上),但其具体位置对用户是透明的。
    • 核心用途: 推荐用于持久化由容器内部进程管理和写入的数据,如数据库文件、应用程序生成的日志、用户上传内容等。
    • 优点: Docker 管理、可移植性高、通常性能更好(尤其在 macOS/Windows)、权限处理相对简单。
  2. 绑定挂载 (Bind Mounts):

    • 特点: 将宿主机上的一个现有文件或目录直接映射到容器内的一个路径。用户完全控制宿主机上的路径。
    • 核心用途: 推荐用于将宿主机上的配置文件、源代码(尤其是在开发环境)、或特定的工具/证书等由宿主机直接管理和编辑的内容提供给容器。
    • 缺点: 强依赖宿主机目录结构、权限问题(UID/GID不匹配)常见且处理复杂、在 macOS/Windows 上性能可能较低。

选择原则总结:

特性 命名卷 (Named Volumes) 绑定挂载 (Bind Mounts)
管理方 Docker 用户/宿主机
位置 Docker 管理的特定区域 (对用户透明) 用户指定的宿主机绝对路径
主要用途 应用数据 (数据库, 日志, 上传文件) 配置文件, 源代码, 宿主机工具/文件
可移植性 低 (依赖宿主机路径)
权限处理 Docker 通常处理较好 复杂,易出错,需手动匹配 UID/GID

Docker Volumes

Docker 数据卷(Volumes)是一种管理容器数据的机制,它允许你在宿主机和容器之间持久化数据、共享数据,并且可以独立于容器生命周期之外进行管理。数据卷是 Docker 推荐的持久化数据的方式,提供了比直接在容器文件系统上存储数据或使用绑定挂载(Bind Mounts)更好的灵活性、性能和管理性。

  • 持久性:即使创建它的容器被删除,数据仍然存在。这是数据卷的核心价值。
  • 共享性:可以在多个运行中或停止的容器间安全地共享数据。
  • 性能:由于数据卷绕过了容器的可写层(通常是联合文件系统 UnionFS),直接在宿主机文件系统上进行操作,因此具有更好的读写性能,尤其是在写密集型应用中。
  • 隔离性:每个数据卷都是相互独立的,一个容器中的操作不会影响到其他容器的数据卷(除非明确共享)。
  • Docker 管理: 由 Docker CLI 或 API 进行管理,方便创建、列出、检查、删除和备份。
  • 驱动支持: 数据卷可以使用不同的驱动程序,允许将数据存储在远程主机或云存储上。

常用命令

bash
# 列出所有的数据卷
docker volume ls

# 查看数据卷的详细信息(包括所在位置,即挂载点Mountpoint)
docker volume inspect <volume_name>

# 创建一个命名数据卷
docker volume create <volume_name>

# 删除所有未使用(未被任何容器挂载)的数据卷 (谨慎操作!)
docker volume prune

# 删除一个或多个指定的数据卷 (如果数据卷正被容器使用,则无法删除)
docker volume rm <volume_name_1> <volume_name_2>

默认情况下,Docker 数据卷会被创建在宿主机的特定目录下,例如在 Linux 系统上通常是 /var/lib/docker/volumes/。如果你创建了一个名为 myvolume 的数据卷,那么其实际数据通常会存储在 /var/lib/docker/volumes/myvolume/_data 路径中。


挂载数据卷到容器中

在启动容器时使用 -v 或更推荐的 --mount 参数来挂载数据卷。

  • 使用 -v (简写,适用于命名卷和绑定挂载):

    bash
    # 挂载命名卷 'myvolume' 到容器的 '/app' 目录
    docker run -d -v myvolume:/app myimage
    
    # 绑定挂载宿主机的 '/host/path' 到容器的 '/container/path'
    docker run -d -v /host/path:/container/path myimage
  • 使用 --mount (更明确、更推荐的语法):

    bash
    # 挂载命名卷 'myvolume' 到容器的 '/app' 目录
    docker run -d --mount source=myvolume,target=/app myimage
    
    # 绑定挂载宿主机的 '/host/path' 到容器的 '/container/path'
    docker run -d --mount type=bind,source=/host/path,target=/container/path myimage
    
    # 只读挂载 (适用于配置文件等)
    docker run -d --mount type=bind,source=/host/config,target=/app/config,readonly myimage
    # 或者使用 -v 的简写:
    # docker run -d -v /host/config:/app/config:ro myimage

    --mount 语法更冗长但更清晰,特别是当需要指定卷驱动或挂载选项时。


在 Dockerfile 中定义卷

还可以在 Dockerfile 中使用 VOLUME 指令来指定一个或多个路径作为匿名卷或用于接收来自宿主机的挂载点。

dockerfile
FROM ubuntu
RUN mkdir /mydata
# 当容器启动时,如果 /mydata 没有被其他方式挂载,Docker 会为它创建一个匿名卷
# 如果启动时通过 -v 或 --mount 指定了 /mydata 的挂载,则会使用该挂载
VOLUME /mydata

注意:Dockerfile 中的 VOLUME 指令创建的是匿名卷(如果运行时未指定命名卷或绑定挂载到该路径),或者它指示 Docker 在此路径挂载数据。对于持久化数据,推荐在 docker rundocker-compose.yml 中明确使用命名卷


备份和恢复数据卷

可以通过运行一个临时容器,将目标数据卷挂载到该容器,并使用另一个卷(通常是绑定挂载到宿主机当前目录)作为备份目标。

bash
# 备份名为 'myvolume' 的数据卷到当前宿主机目录下的 backup.tar
docker run --rm \
  -v myvolume:/data_to_backup \
  -v $(pwd):/backup_destination \
  busybox \
  tar cvf /backup_destination/backup.tar /data_to_backup

这里 /data_to_backup 是容器内数据卷的挂载点,backup.tar 是备份文件名,busybox 是一个轻量级镜像,包含了 tar 工具。


恢复数据卷: 同样地,可以通过另一个临时容器来从备份文件恢复数据到目标数据卷。

bash
# 从当前宿主机目录的 backup.tar 恢复数据到名为 'myvolume_restored' 的数据卷
# (可以恢复到原卷,或新建一个卷进行恢复)
docker volume create myvolume_restored # 如果需要恢复到新卷
docker run --rm \
  -v myvolume_restored:/data_to_restore \
  -v $(pwd):/backup_source \
  busybox \
  sh -c "cd /data_to_restore && tar xvf /backup_source/backup.tar --strip 1"

--strip 1 (或根据你备份时的目录结构调整) 用于去除 tar 包中的顶层目录。


使用场景示例

  1. 数据库持久化 (核心场景 - 使用命名卷) 当运行一个数据库服务时,如 MySQL 或 PostgreSQL,你需要确保数据库文件保存在一个命名数据卷中,这样即使容器被删除或重新创建,数据也不会丢失。

    bash
    # 创建命名卷
    docker volume create mysql_db_data
    
    # 运行 MySQL 容器,并将命名卷挂载到 MySQL 存储数据的默认路径
    docker run -d \
      --name my_mysql_db \
      -e MYSQL_ROOT_PASSWORD=mysecretpassword \
      --mount source=mysql_db_data,target=/var/lib/mysql \
      mysql:8.0
  2. 开发环境代码同步 (使用绑定挂载) 开发人员可以将宿主机上的项目代码目录绑定挂载到容器内的应用工作目录,这样在宿主机修改代码后无需重建镜像即可在容器内看到效果,非常适合热重载或快速迭代。

    bash
    # 将宿主机当前目录下的 'my_project_src' 绑定挂载到容器的 '/app/src'
    docker run -d -p 8080:80 \
      --name dev_web_app \
      --mount type=bind,source=$(pwd)/my_project_src,target=/app/src \
      my_dev_image
  3. 配置文件管理 (使用绑定挂载,通常只读) 将宿主机上的配置文件绑定挂载到容器内,方便修改配置而无需进入容器或重建镜像。

    bash
    # 将宿主机 '/etc/my_app/config.ini' 绑定挂载到容器 '/app/config/config.ini' (只读)
    docker run -d \
      --name configured_app \
      --mount type=bind,source=/etc/my_app/config.ini,target=/app/config/config.ini,readonly \
      my_app_image
  4. 多容器间的共享数据 (使用命名卷) 如果你有多个容器需要访问并可能修改相同的数据集(例如,一个Web应用和一个后台处理任务都需要读写共享的缓存或文件),可以使用命名数据卷实现共享。

    bash
    docker volume create shared_app_data
    
    docker run -d --name web_frontend \
      --mount source=shared_app_data,target=/usr/share/data \
      frontend_image
    
    docker run -d --name backend_processor \
      --mount source=shared_app_data,target=/mnt/shared_processing_data \
      backend_image

    注意:当多个容器同时写入共享卷时,需要应用程序层面进行并发控制,避免数据损坏。

  5. 定期备份 (结合命名卷和备份策略) 定期对重要的命名数据卷进行备份是非常重要的。你可以设置定时任务(cron jobs)来自动执行上面提到的备份脚本。