链接:https://www.runoob.com/docker/docker-tutorial.html

Docker 介绍

  • 核心解决问题

    • 解决了 环境的一致性问题 ,实现了对应的一次编写,多平台运行的能力

    • 解决了 依赖管理的复杂性 ,实现的是将应用实现打包,然后发布镜像,多设备进行部署的能力

    • 更加 轻量级 了吧,每个容器化的应用共享一个虚拟环境,核心针对于虚拟机的劣势吧,单机服务的劣势解决

    • 更加快速的部署,过往的部署的是拉取不用的依赖,配置 nginx jvm go nodejs 环境,但是现在只需要进行统一的管理即可快速打包镜像,实现快速的运行部署实现,但是核心还需要做的就是 firewall-cmd 的端口开放即可吧

    • 增强应用的可移植性,一次编译,多端运行的能力实践

  • 容器化的核心概念

    • 应用和环境被打包成不可变的镜像

    • 每次部署都是使用想用的镜像

    • 配置通过环境变量注入或者配置文件读取注入,实现了可配置化

    • 问题的修复通过重新构建镜像,不用再次修改运行中的容器吧

Docker 核心概念

  • 镜像(Image)

    • 是一个只读的模板,包含了运行应用所需的内容,代码,运行时,库文件,环境变量和配置文件吧

      • 分层存储:镜像有多层组成,每一层待变一次修改

      • 只读性:镜像本身是只读的,不可被修改吧

      • 可复用:同一个镜像可以创建出多个单独运行的容器吧

      • 版本管理:通过标签 tag 进行版本管理实现吧

    • 镜像本身的话就不是一个运行时的东西,但是可以复用的产生 container 实现运行和部署

  • 容器(Container)

    • 也就是镜像的运行实例,是一个轻量级、可移植的执行环境吧

      • 隔离性:每个容器拥有自己的文件系统、网络、进程空间

      • 临时性:容器可以被创建、启动、停止、删除吧

      • 可写性:容器在镜像基础上增加了可写性的特性吧

      • 进程级:容器内通常运行一个主进程(进程是操作系统资源分配的最小单位,线程的程序运行的最小单位)

  • 仓库(Repository)

    • 仓库是存储和分发镜像的地方,可以包含多个镜像,镜像可以是多个版本

    • 仓库分类

      • 公共仓库

      • 私有仓库

      • 官方仓库

Docker 组件

补充概念吧:

  • 进程分类

    • 1. 按照交互方式进行区分

      • 交互式进程:依赖用户终端操作(命令行或者图形界面),退出终端,进程结束

      • 守护进程:后台长期运行,无终端交互,系统启动时自动加载吧

    • 2. 按照声明周期分类

      • 短期进程:执行完任务后立即退出,生命周期极短,这个就是短期进程

      • 长期进程:生命周期很长,依赖于本身的操作系统的启动和关闭,和操作系统同时间的(或者整个应用程序的启动时长同步吧)

    • 3. 功能角色分类

      • 系统进程:操作系统内核或底层服务,负责资源管理、进程调度

      • 服务进程:用户启动的应用程序,依赖系统资源运行(Application)

      • 用户进程:提供网络或系统服务的后台进程(守护进程的子集,更强调 “服务化”)

  • 核心概念总结

    • 理解进程和线程的区别

      • 1.1 概念:

        • 进程:操作系统分配资源(内存、文件描述符)的最小单位,拥有独立地址空间,是程序运行的实例。

        • 线程:进程内的执行单元,是 CPU 调度和执行的最小单位,共享所属进程的资源。

      • 1.2 业务总结

        • 进程通信:多程序隔离运行时使用(如不同服务间通信,常用管道、消息队列,ipc)。

        • 线程通信:单程序内多任务并行(如 Web 服务器处理请求,共享内存 + 锁保证安全)。

        • 调度特点:线程调度响应更快,适合 IO 密集型 / 计算密集型并行任务;进程调度隔离性更强,适合独立任务运行。

  • Docker Client(Docker客户端)

    • 是使用docker 的用户和docker进行交互的主要方式吧

    • 接受用户命令并发送给 docker Daemon(Docker 后台守护进程)

    • 可以和远程的 Docker Daemon 进行通信吧

    • 常用的命令是

      • 1. docker run 运行容器

      • 2. docker build 构建容器

      • 3. docker pull 拉取镜像

      • 4. docker ps 查看容器状态

  • Docker Daemon(Docker 后台守护进程)

    • 功能

      • Docker 的核心服务进程

      • 管理镜像、容器、网络和存储卷

      • 监听的是 docker 的 API 请求并且发送处理的

    • 主要的职责

      • 镜像管理

      • 容器生命周期管理

      • 网络管理

      • 数据卷管理

      • 和 Registry 通信吧

  • Docker Engine

    • client 发送命令给 daemon

    • daemon 解析并且执行命令

    • 和 registry 进行交互

    • 管理本地的镜像和容器

    • 返回结果给 client

docker 的核心组件含有: Docker Client Docker Daemon Docker Engine Docker Registry Docker Network Docker Volume

Docker 架构

  • 这个图也是十分的清晰的讷,这里慢慢帮助大家分析分析吧

    • 1. 用户在 docker client 中输入对应的命令docker run docker build docker pull 等命令进行和 docker 命令行交互界面进行交互

    • 2. docker daemon 进行接受到命令行交互界面发送的执行命令,对其进行解析和执行

    • 3. 执行的同时会进行判断,如果本地有 image ,直接通过本地就有的对应的 image 构建出 container

      • 如果本地 local 没有image,就回去 docker registry 进行拉取 image ,再次构建 container

    • 4. 最后本地开发了镜像需要发布也是会进行向 docker registry 进行传输文件以及版本变更 tag 的操作的讷

Docker 安装

  • 关于docker环境安装的实践这里就不进行一一阐述了,因为很简单的讷,以及我和你的环境可能是不一样的,因为我

    • 一会 windows(实习离职后【或者实习转正请假回学校进行休息了】)

    • 一会 macos (实习期间使用公司配备的设备,就是 macos pro M1/2/3)等吧

    • 一会 centos-stream 书写个人项目的时候的服务器的操作运行

  • 由于我的设备环境也是多变的,没有实现统一化管理,所以说这里就不进行详细的讲解把,因为我都是多变的,这个安装的讲解就没有很必要了,哈哈哈!!!

  • 核心就是在本地安装一下 docker docker-compose 就行了把,dockerhub是会将这些 docker 的核心组件进行对应的集成的,直接安装可视化界面就行,对于服务器操作只要依赖于我们的 systemctl 即可吧

  • 安装细节直接略……

Docker 命令行操作

  • 拉取镜像的操作集成吧docker pull [image_name:image_tag] 【docker pull nginx:latest】

  • 显示本地的images镜像吧 docker images

  • 自定义的构建镜像 docker build -t [image_name:tag] Dockerfile

  • 创建并且启动进程

docker run [选项] [镜像名:标签]
# 常用选项:
-d  # 后台运行(守护态)
-p 主机端口:容器端口  # 端口映射(示例:-p 8080:80 映射主机8080到容器80)
-v 主机目录:容器目录  # 挂载数据卷(持久化数据,示例:-v /data:/app/data)
--name [容器名]  # 给容器命名(示例:--name my-nginx)
# 完整示例:docker run -d -p 80:80 --name my-nginx nginx:latest
  • 查看容器状态 docker ps

  • 容器的重启和启动

docker start [容器ID/容器名]  # 启动停止的容器
docker stop [容器ID/容器名]   # 停止运行中的容器
docker restart [容器ID/容器名] # 重启容器
docker kill [容器ID/容器名]   # 强制终止容器(类似nginx -s stop)
  • 进入容器内部

docker exec -it [容器ID/容器名] /bin/bash  # 交互式进入容器终端(大部分Linux镜像用bash)
docker exec -it [容器ID/容器名] sh         # 部分精简镜像用sh(如alpine基础镜像)
  • 删除容器

docker rm [容器ID/容器名]  # 单个删除(需先停止容器)
docker rm -f [容器ID/容器名]  # 强制删除运行中的容器
docker rm $(docker ps -a -q)  # 批量删除所有容器(谨慎使用)
  • 镜像分发

    • 先进行登录 docker login [如果是私有镜像,这里指定链接即可]

    • 给镜像打标签docker tag [本地镜像名:标签] [仓库地址/用户名/镜像名:标签]

      • docker tag my-app:v1 username/my-app:v1 → docker push username/my-app:v1

  • 数据卷操作

docker volume create [卷名]  # 创建数据卷
docker volume ls  # 列出所有数据卷
docker volume rm [卷名]  # 删除数据卷
  • 网络操作

docker network create [网络名]  # 创建自定义网络(容器间通信更灵活)
docker network connect [网络名] [容器名]  # 将容器加入网络
docker network ls  # 列出所有网络

Dockerfile 编写

  • dockerfile 是构建 docker 镜像的伟大蓝图吧,通过指令化描述定义镜像的构建流程,核心追求的是 镜像体积最小化、构建速度最优化、运行安全最大化 的核心理念吧

核心逻辑

  • Docker 镜像采用的是 分层存储机制 ,每一个 dockerfile 执行对应一层镜像层,层与层之间是相互依赖且只读的(容器只有在运行时 container 的时候才是可写的)。构建的时候 docker 会按照指令顺序执行,且自动缓存已构建的层,以及实现复用缓存的特性,实现提高构建效率的特性吧

三要素总结

  • 构建上下文:执行 docker build 的时候是可以指定目录的,该目录就是 dockerfile 的上下文目录,在执行的是后 dockerfile 会把当前工作目录的文件实现传输给 Docker 的守护进程(Daemon),作为构建的基础文件集

  • Dockerfile:位于构建上下文的根目录吧,也可以通过 -f 实现指定目录的,是一个包含了构建指令的文本文件吧

  • .dockerignore 文件:过滤构建上下文无需传输的文件,减少传输体积并避免敏感信息的泄露等问题吧

核心需要掌握

实战指导设计

  • 基础镜像的选择

    • 基础镜像的选择直接决定了镜像的基准体积和安全性的问题吧,避免使用全量系统镜像

      • 1. 语言专属精简镜像版本: alpine slim

      • 2. Apline 镜像,比较轻量级的镜像版本吧

      • 3. 固定版本号的镜像:禁止使用 latest 标签的镜像,避免构建一致性问题

  • 分层优化:合并指令+清理冗余

    • docker 的每层都会保留指令执行痕迹,过多的层数或冗余文件会大幅增加体积的讷

      • RUN 指令合并:用 && 链接相关命令\ 换行保持可读性

      • 及时清理缓存:安装依赖后立即清理包管理缓存

      • 禁用不必要的依赖

稳定前,变动后

  • 稳定指令存放前面,变动指令存储后面

    • 先实现复制依赖描述文件 pom.yml package.json go.mod

    • 最后复制源代码

FROM node:18-alpine
WORKDIR /app
# 先复制稳定的依赖文件,缓存安装结果
COPY package.json package-lock.json ./
RUN npm ci --only=production  # 仅安装生产依赖
# 最后复制频繁变更的源码
COPY src ./src
EXPOSE 3000
CMD ["node", "src/server.js"]

多阶段构建

  • 分离构建和运行环境

  • 编译型语言(Java、Go、Rust)需构建工具链(如 maven、gcc),但运行时无需,多阶段构建可彻底剥离构建环境,使镜像体积减少 60% 以上

# 第一阶段:构建阶段(含 Maven 工具链)
FROM maven:3.8-openjdk-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline  # 缓存依赖,后续构建复用
COPY src ./src
RUN mvn package -DskipTests  # 构建出 jar 包

# 第二阶段:运行阶段(仅含 JRE 运行时)
FROM openjdk:17-jre-slim
WORKDIR /app
# 仅从构建阶段复制产物,剥离构建工具
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
# 构建阶段:编译二进制文件
FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 交叉编译为无依赖二进制
RUN CGO_ENABLED=0 GOOS=linux go build -o app .

# 运行阶段:使用空镜像 scratch(仅 2MB 左右)
FROM scratch
# 复制编译产物和必要证书(如需网络请求)
COPY --from=builder /app/app /app
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8080
ENTRYPOINT ["/app"]

安全优化

  • 创建专属用户

  • 切换运行用户

  • 只读根文件系统

FROM node:18-alpine
WORKDIR /app
# 创建非 Root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# 复制依赖并安装(Root 权限执行)
COPY package*.json ./
RUN npm ci --only=production
# 复制源码并修改权限
COPY . .
RUN chown -R appuser:appgroup /app
# 切换到低权限用户
USER appuser
# 声明数据卷(用于写入数据)
VOLUME ["/app/data"]
EXPOSE 3000
CMD ["node", "server.js"]

上下文优化

  • 也就是指定 .dockerignore 实现冗余文件系统的构建吧

.git
.gitignore
node_modules
npm-debug.log
.env
.env.local
dist/*.map
*.md
.vscode

Docker-Compose 服务编排指导

Docker Compose 是 Docker 官方推出的容器编排工具,用于定义和运行多个关联的 Docker 容器应用

通过单一的 yaml 文件的配置,即可实现创建、启动、停止、销毁等安全生命周期的管理,大幅的简化了微服务、分布式应用等容器场景的部署流程

核心的配置文件就是 docker-compose.yaml

Docker compose 的字段

根节点的配置字段

services 节点的配置

  • 每个节点都是对应的是对应的服务,需要根据具体的业务场景进行对应的合理的蓝图配置把

# docker-compose.yml(新版本,无 version 字段)
services:
  # Nginx 服务
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d  # 挂载配置文件
      - nginx-log:/var/log/nginx         # 挂载日志卷
    depends_on:
      - web  # 依赖 web 服务,web 启动后再启动 nginx
    networks:
      - app-network
    restart: always

  # 后端 Web 服务(本地构建镜像)
  web:
    build: ./web  # 本地 ./web 目录下有 Dockerfile
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/testdb
      - SPRING_DATASOURCE_USERNAME=root
    env_file:
      - ./web/.env  # 敏感信息(如密码)放单独文件
    depends_on:
      - mysql
    networks:
      - app-network
    restart: always

  # MySQL 服务
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=root123
      - MYSQL_DATABASE=testdb
    volumes:
      - mysql-data:/var/lib/mysql  # 数据持久化卷
    networks:
      - app-network
    restart: always

# 自定义网络(服务间通过服务名通信)
networks:
  app-network:
    driver: bridge  # 桥接模式,默认网络驱动

# 数据卷(跨容器共享或持久化)
volumes:
  nginx-log:
  mysql-data:
  • 核心讲解把

    • services 服务节点有:

      • 1. nginx 服务,依赖于我们的 web 服务

      • 2. web 服务,依赖于我们的 mysql 服务

      • 3. mysql 服务,什么都不依赖,只是一个服务抽象层的进程而已吧

核心命令操作学习