谈谈那些欠下的技术债——Docker

3,329 阅读14分钟

我口袋只剩玫瑰一片此行又山高路远

Docker

什么是Docker?

  • 容器:Docker 容器(Container) 是从镜像创建的运行时实例。它是一个轻量级、独立的环境,可以在多个环境中一致运行,并且彼此隔离。
  • 镜像:容器的模板,包含运行应用程序所需的所有文件、依赖和配置。
  • Dockerfile:用于定义如何构建 Docker 镜像的脚本。
  • Docker Hub:Docker 镜像的公共仓库,可以下载和分享镜像。

Docker架构

  • Docker Client(客户端) :用户交互入口。

  • Docker Daemon(守护进程) :负责处理 Docker 容器、镜像、网络等操作的后台服务。

  • Docker Image(镜像) :创建容器的模板。

  • Docker Container(容器) :镜像的运行实例。

  • Docker 注册表:存储和分发镜像的地方。

  • Docker 网络:容器间的通信。

  • Docker 存储:持久化容器数据。

  • Docker Swarm:容器编排和集群管理工具。

    万字详解Docker架构原理、功能及使用-腾讯云开发者社区-腾讯云

Docker的运行流程

  1. 用户使用 Docker Client 与 Docker Daemon 建立通信,并发送请求给后者;

  2. Docker Daemon 作为 Docker 架构的主体部分,首先提供 Docker Server 的功能,使其可以接收 Docker Client 的请求;

  3. Docker Engine 执行 Docker 内部的一系列工作,每一项工作都是以一个 Job 的形式存在;

  4. Job 的运行过程中,当需要容器镜像时,则从 Docker Registry 中下载镜像,并通过镜像管理驱动 Graph Driver 将下载镜像以 Graph 的形式存储;

  5. 当需要为 Docker 创建网络环境时,通过网络管理驱动 Network driver 创建并配置 Docker 容器网络环境;

  6. 当需要限制 Docker 容器运行资源,或执行用户指令等操作时,则通过 Exec driver 来完成。

    Docker面试题及答案(99%面试官必问必考) – mikechen

容器的隔离是如何实现的?

Docker 通过多种技术实现了容器的隔离,确保容器在共享宿主机资源的同时,互相之间和宿主机之间没有干扰。通过 命名空间控制组文件系统隔离网络隔离安全机制等技术,Docker 能够提供强大的容器隔离性,使得容器化应用在执行时更加安全、独立和高效。

安装

下载地址:Docker: Accelerated Container Application Development

设置镜像源(Settings \ Docker Engine):

{
  "registry-mirrors": [
    "http://hub-mirror.c.163.com",
    "https://docker.mirrors.ustc.edu.cn"
  ],
  "insecure-registries": [],
  "debug": true,
  "experimental": false
}

快速开始

Docker Hello World

cmd 打开并输入:

docker run hello-world

Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world e6590344b1a5: Pull complete Digest: sha256:d715f14f9eca81473d9112df50457893aa4d099adeb4729f679006bf5ea12407 Status: Downloaded newer image for hello-world:latest

Hello from Docker! This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:

  1. The Docker client contacted the Docker daemon.
  2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
  3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
  4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.

To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID: hub.docker.com/

For more examples and ideas, visit: docs.docker.com/get-started…

Docker使用

全局命令

显示 Docker 系统的详细信息
docker info
显示 Docker 客户端和守护进程的版本信息
docker version
显示容器的实时资源使用情况
docker stats
清理不再使用的资源

删除停止的容器、未使用的网络和悬挂的镜像

docker system prune [OPTIONS]

强制清理

docker system prune -f

包括卷在内的完全清理

docker system prune -a --volumes

容器使用

启动容器
docker run
docker run -itd --name tencentos-test tencentos/tencentos_server24
列出正在运行的容器
docker ps

如果需要列出已停止的容器,请执行

docker ps -a
获取容器的详细信息
docker inspect 容器名称
停止容器
docker stop
杀死一个Docker容器
docker kill <container_id>
启动已停止的容器
docker start
重启容器
docker restart 
删除容器
docker rm
查看容器日志
docker logs 容器名称
在运行的容器中执行命令
docker exec -it 容器名称/容器ID bash
docker exec -it tencentos-test bash

退出终端

exit
导出容器(快照)
docker export 容器ID > 快照名称
docker export ac62a76297eb > D:\Docker\Snapshot\tencentos.tar
导入容器快照
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

注:

docker import 仅保留文件系统,丢失历史记录和元数据(如标签和环境变量)。

从本地tar文件导入

cat D:\Docker\Snapshot\tencentos.tar | docker import - my_image:latest

docker import D:\Docker\Snapshot\tencentos.tar my_image:latest

从 URL 直接导入

docker import http://example.com/my_container.tar my_image:latest

添加镜像元数据

cat my_container.tar | docker import --change "ENV LANG=en_US.UTF-8" - my_image:latest

镜像使用

列出镜像列表(查看本地镜像)
docker images
查看镜像详细信息
docker inspect <镜像ID或名称>
拉取镜像
docker pull <镜像名>:<标签>

官方镜像

docker image pull 镜像名称 
# 或简写为 
docker pull 镜像名称

docker pull ubuntu docker pull ubuntu:16.04

个人镜像

docker pull 仓库名称/镜像名称

docker pull xunmi/django

第三方仓库镜像

docker pull 第三方仓库地址/仓库名称/镜像名称

docker pull hub.c.163.com/library/mysql:latest

推送镜像

将镜像推送到远程仓库

docker push <仓库名>/<镜像名>:<标签>
查找镜像
docker search 镜像名称
docker search centos

NAME: 镜像仓库源的名称

DESCRIPTION: 镜像的描述

OFFICIAL: 是否 docker 官方发布

STARS: 类似 Github 里面的 star

删除镜像
docker rmi <镜像ID或名称>

强制删除镜像

docker rmi -f <镜像ID或名称>

删除未被使用的镜像

docker image prune

删除所有未使用的镜像

docker image prune -a
构建镜像
构建镜像的原则
  • 尽量保持镜像精简
  • 避免在容器中使用 root 用户
  • 合并相关指令、减少层数
  • 尽量缓存中间层
  • 明确指定版本,避免使用latest 标签
  • 尽量减少容器暴露的端口
  • 清理缓存和临时文件
  • 正确使用 ENTRYPOINTCMD 指令来指定容器的启动命令
  • 保持 Dockerfile 可读性
  • 避免暴露敏感信息
从现有镜像创建
  • 你在容器里安装了新软件,想要保存这次修改。
  • 修改了配置文件,希望创建新的镜像,以后直接使用这个配置。
  • 你想基于现有容器创建一个新的基础镜像,而不使用 Dockerfile 重新构建。
docker commit [选项] <容器ID或名称> <新镜像名>:<标签>

指定作者信息

docker commit -a "Your Name <your.email@example.com>" my_container my_custom_ubuntu:latest

指定提交信息

docker commit -m "Added vim and updated packages" my_container my_custom_ubuntu:latest

多个选项

docker commit -a "Your Name" -m "Installed vim and curl" my_container my_custom_ubuntu:v1
使用Docker File 创建
docker build [选项] <上下文目录>
docker build -t my_image:latest -f /path/to/Dockerfile .
选项描述
-t给构建的镜像打标签,格式为 name:tag,例如 my_image:latest
-f指定 Dockerfile 的路径,默认是当前目录下的 Dockerfile
--no-cache禁用缓存,不使用之前构建的缓存层,强制从头开始构建
--build-arg设置构建时的参数,传递给 Dockerfile 中的 ARG 指令
--pull始终尝试拉取最新的基础镜像
--quiet安静模式,只输出构建镜像的 ID
--rm构建完成后删除临时容器,默认为 true
--target构建指定的阶段,适用于多阶段构建(见下面示例)
Dockerfile 和 docker commit
  • 通过 Dockerfile 创建镜像:适用于需要复现、版本控制的镜像构建,推荐用于生产环境中的镜像管理。
  • 通过 docker commit 创建镜像:适用于快速保存容器的当前状态,适合实验性或临时操作,但不适用于长时间管理和维护。
镜像归档(导出镜像)

将一个或多个 Docker 镜像导出为 tar 归档文件,方便备份、传输或导入到另一台机器。

docker save -o <文件名>.tar <镜像名>:<标签>

docker save <镜像名:标签> > <输出文件>

保存单个镜像

docker save -o my_image.tar my_image:latest

保存多个镜像

docker save -o my_images.tar my_image1:latest my_image2:v1

保存压缩镜像

docker save my_image:latest | gzip > my_image.tar.gz
恢复镜像

docker load 用于docker save 生成的 tar 归档文件加载 Docker 镜像,通常用于镜像备份恢复或迁移到其他机器。

docker load -i <文件名>.tar

cat <镜像文件> | docker load

从 tar 文件加载镜像

docker load -i my_image.tar

从加载 gzip 压缩的镜像

gunzip -c my_image.tar.gz | docker load
查看镜像历史
docker history <镜像名>:<标签>
标记镜像
docker tag <镜像ID或名称> <新名称>:<新标签>

Docker File

一个 Dockerfile 由多条指令(Instruction) 组成,每条指令都会在构建镜像时执行。

# 1. 指定基础镜像(FROM)
FROM ubuntu:latest  

# 2. 维护者信息(可选)
LABEL maintainer="your.email@example.com"

# 3. 运行命令(RUN)
RUN apt-get update && apt-get install -y curl vim  

# 4. 复制文件到镜像中(COPY)
COPY my_script.sh /usr/local/bin/my_script.sh  

# 5. 设置工作目录(WORKDIR)
WORKDIR /usr/local/bin  

# 6. 指定容器启动时执行的命令(CMD)
CMD ["bash"]  

CMDENTRYPOINT 的区别

  • CMD 命令设置容器启动后默认执行的命令及其参数,但 CMD 设置的命令能够被docker run 命令后面的命令行参数替换
  • ENTRYPOINT 配置容器启动时的执行命令(不会被忽略,一定会被执行,即使运行 docker run时指定了其他命令)
  • ENTRYPOINT 的 Exec 格式用于设置容器启动时要执行的命令及其参数,同时可通过CMD 命令或者命令行参数提供额外的参数
  • ENTRYPOINT 中的参数始终会被使用,这是与 CMD 命令不同的一点

Dockerfile中CMD与ENTRYPOINT命令的区别-腾讯云开发者社区-腾讯云

多阶段构建(Multi-Stage Build)

减少最终镜像的大小,可以使用多阶段构建,最终镜像不会包含 Go 编译器,减少体积。

# 第一阶段:构建应用
FROM golang:alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

# 第二阶段:创建更小的最终镜像
FROM alpine
WORKDIR /root/
COPY --from=builder /app/myapp .
CMD ["./myapp"]

Docker网络

Docker中的网络模式

  • bridge:默认模式,容器通过虚拟网桥连接到宿主机的网络。
  • host:容器共享宿主机的网络。
  • none:容器没有网络连接。
  • container:容器与另一个容器共享网络。
  • overlay:跨多个 Docker 主机的虚拟网络,通常用于 Docker Swarm 集群中,支持在集群中的容器之间进行通信。
常用命令
指定容器的网络模式
docker run --network <网络模式> 要运行的镜像的名称或 ID
  • --network bridge
  • --network host
  • --network none
  • --network container:
  • --network
列出所有网络
docker network ls
查看网络详情
docker network inspect <network_name>
创建自定义网络
docker network create [OPTIONS] NETWORK_NAME

--driver:指定网络驱动程序(即网络类型)

--subnet:指定子网范围,通常与自定义网络一起使用,定义网络的 IP 范围。

--gateway:为网络指定一个网关地址,通常与 --subnet 配合使用。

--ip-range:为容器分配 IP 地址的范围。此选项指定一个子集的 IP 地址范围,而不是整个子网。

--internal:创建一个内部网络,容器无法访问外部网络(即不允许容器访问互联网)。

--attachable:允许在 Docker Swarm 集群模式下,容器能够附加到 overlay 网络上。

删除网络
docker network rm <network_name>
端口映射
docker run -p <host_port>:<container_port> <image_name>

映射端口

docker run -p 8080:80 my_image

映射多个端口

docker run -p 8080:80 -p 443:443 my_image

自动选择宿主机端口(如果不指定宿主机端口,Docker 会自动选择一个端口进行映射)

docker run -p 80 my_image

映射到特定的 IP 地址

docker run -p 127.0.0.1:8080:80 my_image

使用 -P 自动暴露端口

docker run -P my_image
  • host_port:宿主机上暴露的端口。
  • container_port:容器内应用程序监听的端口。
  • image_name:用于创建容器的镜像。
查看端口映射
docker ps

docker inspect <container_id> | grep "PortBindings"

Docker协调与集群管理

Docker Compose

Compose 是用于定义和运行多容器 Docker 应用程序的工具。

docker-compose.yml

docker-compose.yml 文件采用 YAML 格式,通常包含以下几个主要部分:

  1. version:定义 Compose 文件的版本。
  2. services:定义应用中的所有服务,每个服务代表一个容器实例。
  3. networks:定义服务间通信的网络。
  4. volumes:定义数据卷,用于容器间共享数据或持久化数据。
  5. configssecrets(可选):用于存储配置信息和敏感数据。
多个 Compose 文件
docker-compose.override.yml

docker-compose 中,docker-compose.override.yml 是一个可选的文件,主要用于覆盖或扩展 docker-compose.yml 的默认配置,通常用于开发环境本地调试

docker-compose up -d  # 自动加载 override 文件
合并原则
  • 后面的文件覆盖前面的配置
  • 相同的 servicesvolumes 等会合并
  • environmentportsvolumes 这样的数组不会自动合并,需要手动确保完整性
常用配置选项
  • build:

    • 如果需要从 Dockerfile 构建镜像,可以使用 build 指令。
    web:
      build: ./web
    
  • environment:

    • 设置容器的环境变量。
    db:
      image: mysql:5.7
      environment:
        MYSQL_ROOT_PASSWORD: rootpassword
    
  • volumes:

    • 挂载宿主机目录到容器中。
    web:
      image: nginx:latest
      volumes:
        - ./html:/usr/share/nginx/html
    
  • ports:

    • 映射容器的端口到宿主机端口。
    web:
      image: nginx:latest
      ports:
        - "8080:80"
    
  • depends_on:

    • 定义服务间的启动顺序。depends_on 用于确保服务按顺序启动,例如确保数据库先启动。
    web:
      image: my_web_app
      depends_on:
        - db
    
  • restart:

    • 配置容器的重启策略。
    web:
      image: nginx:latest
      restart: always
    

    可选值:

    • no:不重启。
    • always:总是重启容器。
    • unless-stopped:除非容器被显式停止,否则总是重启。
    • on-failure:仅在容器非零退出时重启。
  • networks:

    • 配置容器使用自定义网络,使它们能够相互通信。
    networks:
      my_network:
        driver: bridge
    
  • extra_hosts:

    • 向容器添加主机名到 IP 地址的映射。
    web:
      image: nginx:latest
      extra_hosts:
        - "example.com:192.168.1.100"
    
常用命令
启动所有服务
docker-compose up

加上 -d 选项可以让服务在后台运行

docker-compose up -d

docker-compose.yml 默认使用 YAML 格式,但也可以使用 JSON 格式编写 docker-compose.json。

docker-compose -f docker-compose.json up -d

还可以使用多个 Compose 文件

docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d 
启动指定服务的容器并运行命令
docker-compose run
启动已经存在的服务
docker-compose start
停止服务
docker-compose down
查看服务日志
docker-compose logs
查看正在运行的容器
docker-compose ps
停止服务但不删除容器
docker-compose stop
停止服务后,删除容器、网络和卷
docker-compose down --volumes

Docker Swarm

Docker Swarm是一个容器编排工具,它允许我们在不同的主机上管理多个容器。通过Swarm,我们可以将多个Docker主机变成一个单一的主机,以便于监控和管理。

Kubernetes

其他

Docker Volumes

Docker Volumes(数据卷) 是 Docker 提供的一种数据持久化机制,用于在容器和宿主机之间共享数据,同时避免数据因容器销毁而丢失。

Docker Volumes 的类型
  • Volumes(数据卷) (推荐)

    • 由 Docker 管理,默认存储在 /var/lib/docker/volumes/ 目录。
    • 容器可以挂载到 Volumes 上,数据不会随容器删除而丢失。
  • Bind Mounts(绑定挂载)

    • 允许将宿主机的任意目录或文件挂载到容器中,而不仅限于 /var/lib/docker/volumes/
    • 宿主机上的文件权限和安全性直接影响容器。
  • tmpfs Mounts(内存挂载)

    • 将数据存储在内存中,不会写入磁盘,适用于高性能临时数据存储的场景。
相关操作
创建 Volume
docker volume create <volume_name>
查看所有 Volumes
docker volume ls
查看 Volume 详细信息
docker volume inspect <volume_name>
使用 Volume 运行容器
docker run -d --name my_container -v <volume_name>:/app busybox
  • docker run:创建并运行一个新的容器。

  • -d以后台模式运行容器(detached mode)。

  • --name my_container:给容器指定名称 my_container(否则会自动分配一个随机名称)。

  • -v <volume_name>:/app

    • -v 选项用于挂载 Docker Volume
    • <volume_name> 是 Docker Volume 的名称。
    • /app 是容器内的挂载路径,表示 容器中的 /app 目录将映射到宿主机上的 <volume_name> 数据卷
  • busybox:使用 busybox 这个轻量级 Linux 镜像。

删除 Volume
docker volume rm <volume_name>
删除所有未使用的 Volumes
docker volume prune

安装CentOS

镜像拉取

因Centos 已被官方停止支持,故不建议继续使用,可以尝试使用 TencentOS Server 2.4 代替

docker pull tencentos/tencentos_server24

CentOS 迁移 TencentOS Server 指引 | 腾讯云

tencentos/tencentos_server24 - Docker Image | Docker Hub

参考文档

从零开始的Docker Desktop使用,Docker快速上手 ( ̄︶ ̄) Docker介绍和基础使用-CSDN博客

Docker 教程 | 菜鸟教程