Skip to content

Docker是什么?

Docker是一个开源的容器平台,可以轻松地创建、运行、分享和部署应用。它允许开发人员将应用程序及其所有依赖项(如库、运行时环境、配置文件等)打包到一个称为 Docker 镜像的可移植容器中。这些容器可以在任何支持 Docker 的环境中以相同的方式运行,无需担心环境差异或依赖问题

Docker简介

Docker通过将应用及其依赖打包到一个标准化的容器中,实现了环境一致性和快速部署。容器是轻量级、可移植、自给自足的软件包,可以在任何支持Docker的主机上运行。相比传统的虚拟机,容器启动更快、资源占用更少,非常适合微服务架构和持续集成/持续部署(CI/CD)场景。

Docker的核心组件包括:

  • 容器引擎(Docker Engine):用于构建和运行容器的服务。容器引擎是一个用于创建、运行和管理容器的软件。最流行的容器引擎是 Docker,但也有其他选择,如 Containerd、CRI-O 等。容器引擎负责与宿主机的操作系统内核交互,以便在其中创建和管理容器。
  • 镜像(Docker Image):应用及其依赖的只读模板。
  • 容器(Docker Container):镜像的运行实例。
  • Docker Hub:官方的镜像仓库,方便分享和分发镜像。

通过Docker,开发者可以更高效地管理应用生命周期,提高开发、测试和运维的效率。

而一个典型的Docker容器架构包括以下组件:

  • 宿主机(Host Machine): 宿主机是运行容器的物理或虚拟计算机。它可以是云服务器、物理服务器或者虚拟机实例。宿主机上安装了容器运行时(如 Docker Engine),负责管理容器的生命周期。
  • 容器引擎(Container Engine): 容器引擎是一个用于创建、运行和管理容器的软件。最流行的容器引擎是 Docker,但也有其他选择,如 Containerd、CRI-O 等。容器引擎负责与宿主机的操作系统内核交互,以便在其中创建和管理容器。
  • 镜像(Image): 镜像是容器运行时的静态文件,包含了应用程序的代码、运行时环境、系统工具和依赖项。镜像是容器的基础,用于创建容器实例。Docker 镜像通常由 Dockerfile 构建而成,可以通过 Docker Hub 或私有镜像仓库分享和分发。
  • 容器(Container): 容器是运行在宿主机上的一个或多个镜像的实例。每个容器都是一个独立的运行环境,包含了应用程序及其所有依赖项,以及所需的配置文件。容器之间是相互隔离的,但可以与宿主机共享资源和网络。
  • 容器编排(Container Orchestration): 容器编排是一种自动化和管理容器化应用程序的方法。它涉及到部署、扩展、管理和调度容器的过程,以确保应用程序的高可用性、负载均衡和弹性。常见的容器编排工具包括 Kubernetes、Docker Swarm 等。
  • 容器注册中心(Container Registry): 容器注册中心是用于存储、管理和分发容器镜像的中心化服务。它允许开发人员和运维团队共享和获取镜像,以便在不同的环境中部署应用程序。常见的容器注册中心包括 Docker Hub、Harbor、Quay 等。

容器技术的代表性实现包括 Docker、Kubernetes、Podman 等。这些工具使得容器的创建、管理和部署变得更加简单和高效,广泛应用于软件开发、测试、部署和运维等领域。

Docker安装

Docker的安装方式有很多种,这里介绍两种最常用的安装方式:

  1. Docker Desktop:适用于Windows和MacOS系统,安装后直接运行Docker Desktop即可。
  2. Docker Engine:适用于Linux系统,需要手动安装Docker Engine和Docker Compose。

注意:Docker Desktop和Docker Engine安装方式不同,但安装完成后的配置和操作方式相同。

  • 安装Docker Desktop
  1. 下载Docker Desktop安装包,并运行安装程序。下载地址alt text
  2. 启动Docker Desktop,并等待初始化完成。
  • 安装Docker Engine
  1. 安装依赖包(以在linux的Ubuntu为例):

在 Linux 上安装 Docker 不同的 Linux 发行版可能有不同的包管理工具和安装步骤。下面我将分别介绍在常见的几种 Linux 发行版上安装 Docker 的方法: 在 Ubuntu 上安装 Docker 在 Ubuntu 上安装 Docker 可以通过 apt 包管理器进行,按照以下步骤操作:

1、更新软件包索引:

bash
sudo apt update

2、安装所需的软件包,以支持通过 HTTPS 使用 Docker 仓库:

bash
sudo apt install apt-transport-https ca-certificates curl software-properties-common

3、添加 Docker 的 GPG 密钥:

bash
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

4、添加 Docker 的APTP仓库:

bash
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

5、更新软件包索引,并安装 Docker Engine:

bash
sudo apt update
sudo apt install docker-ce

6、验证 Docker 安装是否成功:

bash
sudo docker --version

Docker镜像

Docker镜像是一个只读的模板,包含了应用程序及其依赖项。镜像可以基于其他镜像创建,也可以作为基础镜像使用。Docker Hub 是一个公共的镜像仓库,可以分享和获取镜像。 镜像的创建和运行方式如下:

  1. 创建镜像:使用Dockerfile创建镜像。Dockerfile是一个文本文件,包含构建镜像所需的指令。 Dockerfile的格式如下:
dockerfile
# 使用 Node.js 18 简洁版本的官方镜像
FROM node:18-alpine

# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000

# 设置工作目录
WORKDIR /app

# 仅复制依赖文件(提高构建缓存效率)
COPY package*.json ./

# 安装依赖(使用生产依赖)
RUN npm install --production && npm cache clean --force

# 复制剩余代码
COPY . .

# 暴露端口
EXPOSE 3000

# # 健康检查(可选)
# HEALTHCHECK --interval=30s --timeout=10s \
#   CMD curl -f http://localhost:3000 || exit 1

# 容器启动命令
CMD ["node", "app.js"]
  1. 构建镜像:使用docker build命令构建镜像。
bash
docker build -t my-app:latest .
  1. 运行镜像:使用docker run命令运行镜像。
bash
docker run -d -p 3000:3000 my-app:latest
  1. 推送镜像:使用docker push命令将镜像推送到Docker Hub。
bash
docker push my-app:latest

多层镜像

多层镜像是指一个镜像可以基于其他镜像创建,并添加新的层。这样,创建镜像的效率更高,并且可以复用已有的层。 多层镜像的创建和运行方式如下:

  1. 创建基础镜像:创建一个基础镜像,包含应用程序所需的基础依赖项。例如,创建一个 Node.js 18 镜像。
  2. 创建应用程序镜像:基于基础镜像创建应用程序镜像,并添加应用程序代码和依赖项。
  3. 运行镜像:使用docker run命令运行镜像。

💒 一、Docker 镜像是“一层一层叠起来的积木”

想象你在搭乐高:

第1块:底板(操作系统,比如 Alpine Linux)

第2块:装 Node.js

第3块:放 package.json 第4块:装依赖,运行 npm install

第5块:放你的代码

第6块:写好启动命令

每放一块,就是一个新的层(layer)。 而 Dockerfile 的每一行指令(某些除外)都会创建一个新层。

🔍 二、看你的 Dockerfile 对应多少层?

dockerfile
FROM node:18-alpine        # ← 层1:基础镜像(本身已含多层,但对你来说是“第一层起点”)
WORKDIR /app               # ← 层2:创建目录(实际可能合并或优化,但逻辑上是一层)
COPY package*.json ./      # ← 层3:复制文件
RUN npm install --production  # ← 层4:安装依赖(会生成 node_modules)
COPY . .                   # ← 层5:复制源码
CMD ["node", "app.js"]     # ← 不产生新层(只是元数据)

✅ 所以,虽然只有 6 行,但实际构建出的镜像有 4~5 个可存储的层。

你可以用命令验证:

bash
docker build -t my-app .
docker history my-app

输出类似:

text

IMAGE          CREATED        CREATED BY                                      SIZE
a1b2c3d4       2 mins ago     CMD ["node" "app.js"]                           0B
e5f6g7h8       2 mins ago     COPY . .                                        10MB
i9j0k1l2       2 mins ago     RUN npm install --production                    50MB
m3n4o5p6       2 mins ago     COPY package*.json ./                           1KB
q7r8s9t0       2 mins ago     WORKDIR /app                                    0B
<base-image>   2 weeks ago    /bin/sh -c #(nop) CMD ["node"]                  ...

👉 每一行(除了 FROM 和 CMD/EXPOSE 等元指令)基本都对应一个实际的文件系统变更层。

❓ 三、那为什么叫“多层”而不是“几步”?

因为 Docker 把每一步的结果都存成一个只读快照,像洋葱一样包起来:

如果你下次只改了代码(COPY . . 这一行变了),前面的 npm install 层不会重新执行,直接复用。 这就是“构建缓存”机制,全靠“分层”实现。 如果 Docker 不分层,每次都要从头装系统、装 Node、装依赖……那构建速度会非常慢。

四、总结一句话

“多层镜像”不是指你写了多少行命令,而是指 Docker 把构建过程拆成多个可缓存、可复用的文件系统层。每一层代表一次变更,最终叠加成完整镜像。

所以:

你写的 几行 Dockerfile → 被 Docker 转换成多个层 → 组合成 多层镜像。 “多层”是 Docker 内部的存储和构建机制,不是你手动创建的,而是自动产生的。

什么是 Docker-compose ?

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。 它使用一个 YAML 文件来配置应用程序的服务,然后使用一个命令来创建并启动所有服务。 Docker Compose 的主要作用是定义和运行多个 Docker 容器,并管理它们之间的依赖关系。 比如说,我现在有一个 Web 应用程序,它需要两个服务:一个数据库和一个 Web 服务器。 Docker Compose 可以将这两个服务定义成一个 YAML 文件,然后使用 docker-compose up 命令启动这两个服务。只要在用到这两个镜像服务的项目内,有docker-compose.yml文件,且运行 Docker Compose 的目录下 Dockerfile 和 docker-compose.yml 文件都在,就可以使用 docker-compose up 命令启动服务。 以下是一个简单的 Docker Compose 示例:

yml
# 指定 Docker Compose 文件格式版本
# 常用版本:'3.8'(推荐),支持大多数功能
version: '3.8'

# 定义所有要启动的服务(容器)
services:

  # 服务名称:app(你可以自定义,如 web、api)
  app:
    # 构建配置:从当前目录的 Dockerfile 构建镜像
    build:
      context: .           # 构建上下文目录(默认当前目录)
      dockerfile: Dockerfile  # 指定 Dockerfile 文件名(可选)
    image: test_image  # 构建后镜像名称(可选)或对应镜像文件名
    # 自定义容器名称(可选)
    # 如果不设置,会自动生成如:project-app-1
    container_name: test_api_app # 自定义容器名称

    # 暴露端口:将主机端口映射到容器端口
    # 格式:主机端口:容器端口
    ports:
      - "3000:3000"        # 主机3000 → 容器3000
      # - "80:3000"          # 可选:让外部通过80访问(需权限)

    # 设置环境变量(等同于 -e)
    environment:
      NODE_ENV: production     # 节点环境
      PORT: 3000               # 应用监听端口
      DB_HOST: mysql              # 数据库主机名(服务名)
      DB_PORT: 3306            # 数据库端口
      REDIS_HOST: redis        # Redis 主机名
      REDIS_PORT: 6379         # Redis 端口

    # 从文件加载环境变量(推荐用于敏感信息)
    # 文件内容:DB_PASSWORD=secret123
    env_file:
      - .env                   # 加载根目录的 .env 文件

    # 挂载卷(数据持久化或开发热更新)
    volumes:
      - ./:/app             # 开发时:代码热更新(可选)
      - /app/node_modules      # 防止覆盖容器内的 node_modules

    # 启动依赖:确保 db 和 redis 先启动
    # ⚠️ 注意:只等容器启动,不等服务就绪!
    depends_on:
      - mysql
      - redis

    # 重启策略
    # unless-stopped:除非手动停止,否则始终重启
    restart: unless-stopped

    # 健康检查:Docker 定期检查服务是否正常
    # healthcheck:
    #   test: ["CMD", "curl", "-f", "http://localhost:3000/health"]  # 检查健康接口
    #   interval: 30s           # 每30秒检查一次
    #   timeout: 10s            # 超时10秒
    #   retries: 3              # 失败3次标记为不健康
    #   start_period: 40s       # 启动后40秒内不检查(给应用启动时间)

    # 自定义网络(可选,多个服务在同一网络可通信)
    networks:
      - app-network


  # 服务名称:db(PostgreSQL 数据库)
  mysql:
    image: mysql:8.0  # 使用官方 MySQL  镜像
    environment:
      MYSQL_ROOT_PASSWORD: rootpass     # root 密码(可选)
      MYSQL_DATABASE: personalblog_cn       # 创建数据库名
      MYSQL_USER: devConnect     # 用户名
      MYSQL_PASSWORD: Zhou20000322.  # 密码(生产环境建议用 secrets)
    volumes:
      - db-data:/var/lib/mysql  # 持久化数据
    ports:
      - "3306:3306"            # 映射端口(可选,调试用)
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "devConnect", "-pZhou20000322."]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - app-network


  # 服务名称:redis(缓存服务)
  redis:
    image: redis:alpine        # 使用轻量 Redis 镜像
    command: redis-server --appendonly yes  # 开启 AOF 持久化
    volumes:
      - redis-data:/data       # 持久化 Redis 数据
    ports:
      - "6379:6379"            # 映射端口(可选)
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - app-network


# 定义命名卷(由 Docker 管理,数据持久化)
# 即使容器删除,数据也不会丢失
volumes:
  db-data:                    # MYSQL 数据卷
  redis-data:                 # Redis 数据卷


# 定义自定义网络
# 所有服务加入同一网络,可通过服务名通信(如 http://db:5432)
networks:
  app-network:
    driver: bridge            # 使用桥接网络(默认)

常用命令

Docker

单个镜像一般使用 docker run 命令来启动容器。 运行:

docker run -d -p 3000:3000 --name test_image

Docker Compose

多个镜像使用 docker-compose 命令来启动容器。

运行:
docker-compose up -d
停止:
docker-compose down
删除:
docker-compose rm
删除所有容器:
docker rm $(docker ps -aq)
删除所有镜像:
docker rmi $(docker images -q)
删除所有未使用的镜像:
docker rmi $(docker images -f "dangling=true" -q)
删除所有未使用的网络:
docker network rm $(docker network ls -qf dangling=true)
删除所有未使用的数据卷:
docker volume rm $(docker volume ls -qf dangling=true)