【K8s笔记】docker

container structure

1. 分层不是固定死的,但有典型结构

Docker 镜像的层其实是由 Dockerfile 的每一条指令生成的,所以每个镜像的层数和内容都不完全一样,但通常会有一些“典型层”:

常见镜像分层结构举例

假设你的 Dockerfile 是这样写的:

1
2
3
4
5
6
FROM ubuntu:20.04          # 基础层
RUN apt-get update # 安装更新
RUN apt-get install -y python3 # 安装软件
COPY . /app # 复制代码
RUN pip install -r /app/requirements.txt # 安装依赖
CMD ["python3", "/app/app.py"] # 启动命令

那么分层大致如下:

  1. 基础镜像层

    • 例如:FROM ubuntu:20.04
    • 这层包含了 Ubuntu 的所有系统文件。
  2. 依赖安装层

    • 例如:RUN apt-get updateRUN apt-get install -y python3
    • 这层包含了你通过包管理器安装的所有依赖。
  3. 应用代码层

    • 例如:COPY . /app
    • 这层包含了你自己的应用代码和文件。
  4. 应用依赖层

    • 例如:RUN pip install -r /app/requirements.txt
    • 这层包含了 Python 的依赖库。
  5. 启动命令层

    • 例如:CMD ["python3", "/app/app.py"]
    • 这层其实只是设置容器启动时的默认命令,不会生成新的文件系统层。

2. 总结一下常见的几类层

  • 基础操作系统层(例如 Ubuntu、Alpine、CentOS 等)
  • 软件依赖层(通过 apt/yum/pip/npm 等安装的依赖)
  • 应用代码层(COPY/ADD 你的程序代码、配置文件等)
  • 运行环境层(比如虚拟环境、语言运行时等)
  • 配置/元数据层(ENV、LABEL、EXPOSE、CMD、ENTRYPOINT 等,这些有的会生成层,有的不会)

3. 查看镜像实际分层

你可以用命令查看镜像的实际分层:

1
docker history <镜像名>

输出类似于:

1
2
3
4
5
6
IMAGE         CREATED         CREATED BY                                      SIZE
<id> 2 minutes ago /bin/sh -c pip install -r /app/requirements.txt 50MB
<id> 3 minutes ago /bin/sh -c COPY . /app 2MB
<id> 5 minutes ago /bin/sh -c apt-get install -y python3 100MB
<id> 7 minutes ago /bin/sh -c apt-get update 30MB
<id> 10 days ago FROM ubuntu:20.04 70MB

orchestrator

Orchestrator(编排器)这个词在 IT、云原生和容器领域非常常见。它的本意是“指挥者”,在技术语境下,通常指自动化管理和协调大量服务、容器或任务的系统或工具


1. 通俗解释

orchestrator 就像一个“总指挥”,自动安排、部署、管理各种应用或服务,确保它们高效协作、稳定运行。


2. 具体含义

在容器和微服务领域,orchestrator 主要指用来自动部署、管理、扩展和网络连接容器的系统。它能做的事情包括:

  • 自动部署:自动在多台服务器上分配和启动容器。
  • 负载均衡:根据负载情况自动分配资源。
  • 自愈能力:服务或容器挂了会自动重启或替换。
  • 滚动升级/回滚:无缝升级或回退应用。
  • 服务发现和网络管理:让服务之间能互相通信。
  • 资源管理:自动分配 CPU、内存等资源。

3. 常见的 Orchestrator 工具

  • Kubernetes(最流行的容器编排器)
  • Docker Swarm
  • Apache Mesos
  • Nomad(HashiCorp 出品)
  • (数据库领域)Orchestrator 也有专门管理 MySQL 主从拓扑的工具,叫 Orchestrator

4. 应用场景举例

假设你有 100 个微服务,每个服务要运行多个副本在几十台服务器上,还要能自动扩容、自动恢复——

  • 你不可能手动一个个启动、监控、调度、分配资源。
  • 这时候就需要一个 orchestrator 来帮你自动完成这些复杂的调度和管理工作。

Dockerfile

1
2
3
4
5
6
7
FROM alpine
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]

下面是逐行解释:
这个 Dockerfile 的作用是用来构建一个 Node.js 应用的 Docker 镜像,具体解释如下:

  1. FROM alpine

    • alpine 作为基础镜像。Alpine 是一个体积很小的 Linux 发行版,非常适合用来构建轻量级的 Docker 镜像。
  2. RUN apk add --update nodejs nodejs-npm

    • 使用 Alpine 的包管理工具 apk 安装 nodejsnpm(Node.js 的包管理工具)。
    • --update 参数表示更新包索引。
  3. COPY . /src

    • 把当前目录下的所有文件复制到镜像内的 /src 目录下。
  4. WORKDIR /src

    • 设置工作目录为 /src,后续的命令都将在该目录下执行。
  5. RUN npm install

    • 安装项目依赖。会自动读取 /src 目录下的 package.json 文件并安装依赖包。
  6. EXPOSE 8080

    • 声明容器会监听 8080 端口。用于文档和其他开发者了解服务端口,实际端口映射还需 docker run -p 参数。
  7. ENTRYPOINT [“node”, “./app.js”]

    • 设置容器启动时运行的命令,这里是用 node 运行 app.js 文件。这个JSON数组里面有两个值,分别是启动命令和参数

Volume

Docker 的 volume(卷)是用来持久化和管理容器数据的一种机制。简单来说,volume 就是容器和主机之间共享数据的“桥梁”,可以让你保存、迁移、备份数据,而不会因为容器的删除或重建而丢失数据。


1. 为什么需要 volume?

  • 容器里的数据默认是临时的,容器删除后数据就没了。
  • 有些数据(如数据库、日志、上传文件等)需要持久保存,不能随着容器消失。
  • 多个容器可以共享同一份数据

2. volume 的作用

  • 数据持久化:即使容器被删除,数据还在。
  • 数据共享:多个容器可以访问同一个 volume,实现数据共享。
  • 备份恢复:volume 可以很方便地备份和恢复。
  • 分离数据和应用:让应用和数据独立管理,方便升级和迁移。

3. volume 如何使用?

1)命令行挂载

启动容器时用 -v--mount 参数:

1
docker run -d -v mydata:/data myimage

这会将名为 mydata 的 volume 挂载到容器的 /data 目录。

2)在 docker-compose.yml 里

1
2
3
4
5
6
7
8
services:
db:
image: mysql
volumes:
- dbdata:/var/lib/mysql

volumes:
dbdata:

3)Dockerfile 里声明

1
VOLUME /data

这表示建议把 /data 目录作为挂载点,但实际挂载要在运行容器时指定。


4. volume 的类型

  • 匿名卷(没有名字,Docker 自动生成)
  • 命名卷(你自己起名,方便管理)
  • 绑定挂载(直接把主机目录挂进容器)

5. 简单理解

  • volume 就像是“U 盘”,插到容器里,数据就能带走,不怕容器重建。
  • 容器删了,volume 还在,数据不会丢。

6. 数据备份

  • 单独使用busybox容器来挂载volume和本地目录来拷贝文件进行备份

YAML

下面是 YAML(Yet Another Markup Language)的基本语法和格式说明,适合初学者快速了解和入门。


1. 基本结构

  • YAML 是纯文本格式,常用于配置文件(如 Docker Compose、Kubernetes 等)。
  • 以缩进表示层级缩进用空格,不允许用 Tab
  • 文件扩展名通常为 .yml.yaml

2. 语法规则

2.1 键值对

1
key: value

2.2 嵌套结构(缩进表示层级)

1
2
3
parent:
child1: value1
child2: value2

一般用 2 个空格缩进(也可以 4 个,但要统一)。

2.3 列表(数组)

1
2
3
4
fruits:
- apple
- banana
- orange

2.4 字典嵌套列表

1
2
3
4
5
servers:
- name: server1
ip: 192.168.1.1
- name: server2
ip: 192.168.1.2

2.5 列表嵌套字典

1
2
3
4
- name: Tom
age: 20
- name: Jerry
age: 22

2.6 注释

1
2
# 这是一个注释
name: Alice # 行尾也可以加注释

2.7 字符串、数字、布尔值

1
2
3
4
5
6
string: "hello"
number: 123
float: 3.14
boolean_true: true
boolean_false: false
null_value: null

2.8 多行字符串

1
2
3
description: |
这是一个多行字符串
第二行内容

| 保留换行,> 会折叠成一行。


3. 常见错误

  • 缩进必须一致(同一级别用相同数量的空格)。
  • 不能用 Tab,只能用空格。
  • 冒号后面要有空格

4. 示例

1
2
3
4
5
6
7
8
9
10
person:
name: Alice
age: 25
skills:
- Python
- Docker
- Kubernetes
address:
city: Beijing
zip: 100000

Docker Compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它允许你通过一个 docker-compose.yml 文件来配置应用程序中所有的服务(容器),然后只需一个命令就可以启动、停止和管理这些服务。

主要作用

  • 一站式管理多个容器:比如你的应用有 Web 服务、数据库、缓存等,可以用一个 Compose 文件统一管理。
  • 简化部署流程:只需执行 docker compose up,所有服务就会自动按配置启动。
  • 环境一致性:开发、测试、生产环境配置一致,避免“在我电脑上没问题”的情况。

典型用法

  1. 编写 docker-compose.yml 文件
    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    version: '3'
    services:
    web:
    image: nginx
    ports:
    - "8080:80"
    db:
    image: mysql
    environment:
    MYSQL_ROOT_PASSWORD: example
  2. 启动服务

    1
    docker compose up
  3. 停止服务

    1
    docker compose down

适用场景

  • 微服务架构
  • 本地开发环境快速搭建
  • 自动化测试环境
  • 复杂应用的多容器编排

总结

Docker Compose 就像“容器编排脚本”,让你可以用一个配置文件和几个简单命令,轻松管理一组相关联的容器,非常适合开发和测试阶段使用

docker compose feature

resources

1
2
3
4
5
6
7
8
9
10
11
services:
redis:
image:
deploy:
resources:
limits: # max usage
cpus: '0.50'
memory: 150M
reservations: # min usage
cpus: '0.25'
memory: 20M

ENV variables

1
2
3
4
5
6
services:
web:
image: "go-${GO_VER}:alpine"
environment:
- DEBUG=1
- FOO=BAR

运行的时候参数可以覆盖docker compose up -d -e DEBUG=0,环境变量直接被docker容器内的程序调用。至于${GO_VER},是宿主的环境变量,可以放在项目根目录的.env文件里面,也可以export GO_VER=1.24.1,也可以丢到rc文件里面去

networking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
services:
web:
image:
ports:
- "8080:80"
networks:
- frontend_net

db:
image:
ports:
- "5432"
networks:
- backend_net

networks:
frontend:
driver: bridge
backend:
driver: bridge

默认使用的是default网络,compose内的所有服务都可以互相访问到。在 Docker Compose 的 networks 配置中,driver 用于指定网络类型。常用的 driver 有以下几种


1. bridge

  • 默认驱动,适用于单主机上的容器互联。
  • 适合大多数开发和测试场景。
  • 示例:
    1
    2
    3
    networks:
    mynet:
    driver: bridge

2. host

  • 容器直接使用宿主机的网络栈,没有网络隔离。
  • 适合需要高性能网络通信的场景(如端口映射无效)。
  • 仅支持 Linux。
  • 示例:
    1
    2
    3
    networks:
    mynet:
    driver: host

3. overlay

  • 用于 Docker Swarm 多主机集群环境,实现跨主机容器通信。
  • 需要 Docker Swarm 支持。
  • 示例:
    1
    2
    3
    networks:
    mynet:
    driver: overlay

4. macvlan

  • 让容器拥有独立的 MAC 地址,像物理主机一样出现在局域网。
  • 适用于需要与物理网络直接通信的场景。
  • 示例:
    1
    2
    3
    4
    5
    networks:
    mynet:
    driver: macvlan
    driver_opts:
    parent: eth0

5. none

  • 容器没有网络功能,完全隔离。
  • 示例:
    1
    2
    3
    networks:
    mynet:
    driver: none

6. 第三方/自定义驱动

  • 还有一些第三方网络插件(如 weavecalico 等),需要单独安装。

总结表

driver 作用/场景
bridge 单主机容器通信(默认)
host 容器与主机共用网络,无隔离
overlay 多主机容器通信(需要 Swarm)
macvlan 容器作为独立主机出现在物理网络
none 无网络,完全隔离
第三方 如 weave、calico,需额外安装

dependence

1
2
3
4
5
6
7
8
9
services:
app:
image:
depends_on:
- db
db:
image:
networks:
- nw1

依赖,决定start的顺序

volume

docker-compose.yml 文件中,volumes 用于定义数据卷。你可以在文件底部全局定义卷,也可以在服务内挂载卷。
volumes 相关的常用参数如下:


一、全局 volumes 定义部分的参数

1
2
3
4
5
6
7
8
9
10
11
volumes:
mydata:
driver: local
driver_opts:
type: none
device: /path/on/host
o: bind
labels:
com.example.description: "My volume"
name: my-custom-volume-name
external: true

1. driver

  • 指定卷的驱动,默认 local
  • 例如:driver: localdriver: nfsdriver: glusterfs等。

2. driver_opts

  • 驱动的选项,取决于所用驱动。
  • 常用于本地目录绑定(type, device, o: bind)或远程存储配置。

3. labels

  • 给卷打标签,便于管理和识别。

4. name

  • 指定卷的实际名称(一般不用,除非要自定义卷名)。

5. external

  • 指定该卷是外部已存在的卷,而不是由 Compose 创建。

二、服务内挂载卷的参数

1
2
3
4
5
6
services:
db:
image: mysql
volumes:
- mydata:/var/lib/mysql:ro
- ./local-dir:/container-dir:rw

1. source:target[:mode]

  • source:卷名、主机路径或匿名卷(如 mydata./data)。
  • target:容器内的路径(如 /var/lib/mysql)。
  • mode:挂载模式,ro(只读),rw(读写,默认)。

2. type

  • 指定挂载类型(volumebindtmpfs)。
  • 只有在使用扩展语法时才用到:
1
2
3
4
5
volumes:
- type: volume
source: mydata
target: /data
read_only: true

3. read_only

  • 是否只读挂载(布尔值)。

4. consistency

  • 用于 macOS,指定一致性(consistentcacheddelegated)。

三、完整示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
version: '3.8'
services:
app:
image: myapp
volumes:
- mydata:/data:ro
- ./local:/mnt/local:rw
- type: tmpfs
target: /tmp

volumes:
mydata:
driver: local
driver_opts:
o: bind
type: none
device: /absolute/host/path
labels:
usage: "persistent data"

四、常见场景简表

参数 位置 作用/说明
driver 全局 卷驱动类型(local、nfs等)
driver_opts 全局 卷驱动的额外参数
labels 全局 标签
external 全局 是否引用外部已存在卷
name 全局 指定卷的实际名称
source 服务 卷名或主机路径
target 服务 容器内路径
mode 服务 ro/rw 只读/读写
type 服务 volume/bind/tmpfs
read_only 服务 布尔值,是否只读
consistency 服务 macOS 专用一致性参数

restart policy

在 Docker Compose 的 services 部分,可以通过 restart 参数设置容器的重启策略(restart policy)。这决定了容器在异常退出、主机重启等情况下是否自动重启。


常用的 restart 策略

策略 说明
no 默认值,不自动重启容器。
always 无论退出状态如何,总是自动重启容器。
on-failure 仅在容器非正常退出(退出码非0)时自动重启,可指定最大重启次数。
unless-stopped 总是重启容器,除非用户手动停止docker stop)。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
services:
web:
image: nginx
restart: always

app:
image: myapp
restart: on-failure:3 # 最多重启3次

worker:
image: worker
restart: unless-stopped
  • on-failure[:max-retries] 可以指定最大重启次数,例如 on-failure:5
  • 只写 on-failure 表示无限重启,直到成功退出或被手动停止。

总结

  • 开发环境建议用 no 或不设置。
  • 生产环境常用 alwaysunless-stopped
  • 只想在异常退出时有限制地重启,用 on-failure:3 这类写法。

【K8s笔记】docker
https://学习.fun/k8s-note/k8s-docker/
Author
Stephen Zeng
Posted on
April 29, 2025
Licensed under