Mastodon

docker容器化技术的原理和实现(学校作业)

docker容器化技术的原理和实现(学校作业)

docker的起源与特点:

docker首次发布于2013年3月13日,是一种操作系统层虚拟化,但是与虚拟机不同的是,docker 容器利用主机操作系统的内核,通过“隔离技术”为应用程序提供一个独立的运行环境。
docker和虚拟机(比如virtua box,vmware workstation) 都可以虚拟运行操作系统,但是docker 容器不能像某些虚拟机那样直接运行在裸机硬件上,而必须依赖于一个宿主机操作系统。比如docker可以运行在MacOS、Windows、Linux等主流操作系统上。
Docker 容器运行在宿主机操作系统之上,并共享其内核,而不是像虚拟机那样虚拟化整套硬件。

docker解决了什么问题:

一般来说,在每台电脑上的开发环境都是不同的,这就导致一个项目能运行在我的电脑,但是不能直接在你的电脑上运行。有两个常见的方法:

  1. 第一个是修改自己的开发环境,但是版本依赖层层相扣,堪称依赖地狱,费时费力还可能摧毁现有的开发环境。
  2. 第二个是使用虚拟机,但是使用虚拟机配置开发环境也需要大量时间,还十分消耗电脑性能,因为虚拟机的很多硬件开销是不必要的。

直到docker的出现,极大改善了这一现象,想象一个场景:你发现了一个有趣但是古老的项目A,你想要继续开发维护它:当你下载下来这个项目,发现它使用了Python2.7.10(我的电脑上python版本为3.10.11

依赖使用了

  • numpy 1.11.0(这是Python 进行科学计算的基础包)
  • pandas 0.18.1(数据处理与分析工具)
  • scikit-learn 0.17.1 (机器学习库)
  1. 由于你使用的是python3,但是代码是python2语法,无法运行,于是你选择安装python 2.7.10,还要为此管理多个版本的Python
  2. 当你安装号python 2.7.10后,使用pip install -r requirements.txt报错发现pandas 0.18.1需要numpy>1.21.0,导致版本冲突scikit-learn 0.17.1无法使用新版C++编译器编译,安装失败
requirements.txt是一个纯文本文件,用于列出python项目所依赖的所有第三方软件包及其精确版本。

Pip 为 Python install package
  • 或者软件包A 1.0依赖lib-x 3.0,而软件包B 1.2依赖lib-x 4.0,软件包A B无法在同一环境下共存。这是传递依赖冲突,不是直接的冲突,仍然会导致失败

我曾经就因为想要自行编译ffmpeg,因为依赖地狱最后放弃自编译。

那么docker是如何如何解决的:

  1. 使用一个安装了python 2.7.10 的Linux镜像,这个镜像只包括最基础的系统和环境
  2. 因为Python版本、编译器版本与这些古老库诞生的年代一致,所以安装成功率极高
  3. 将整个系统保存下来,打包为镜像。

docker的安装:

此处主要讲解Linux和Windows如何安装使用docker,两者大部分是互通的

windows的docker运行在WSL2(Windows Subsystem for Linux 2)上

docker、docker compose安装

docker推荐从docker官方APT源下载,Debian官方的APT源内的docker一般较久,甚至还在使用docker-compose 而非 docker compose

以我最熟悉的Debian12为例

  1. 卸载关于docker的所有过去的包,他们可能导致冲突sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-doc podman-docker containerd runc | cut -f1)docker engine过去使用containerdrunc,现在已经捆绑为一个包containerd.iopodman为下一代虚拟化技术
  2. 设置docker官方源
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update

由于Kail Linux为Debian12衍生而来,需要将$(. /etc/os-release && echo "$VERSION_CODENAME")替换为bookworm,这是debian12的代号。

  1. 安装docker最新版
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

docker将在安装后自启动,通过sudo systemctl status docker验证docker是否正常启动

保险起见可以先运行sudo systemctl start docker启动docker,也可以验证docker是否安装

  1. 将用户添加到docker组

切换到要添加到docker组的用户,比如jay

su jay
sudo usermod -aG docker $USER
exit # 推出当前用户,更新状态
su jay
id # ···994(docker)
  1. 更新docker源

docker需要更换国内镜像源才能正常使用,docker源主要有

gcr.io (k8s)
quay.io (redhat)
ghcr.io (github)
docker.io (docker inc)
  1. 找到一个可用的docker镜像源
  2. 修改文件 /etc/docker/daemon.json
sudo nano /etc/docker/daemon.json
# 默认配置:
{
    "runtimes": {
        "runsc": {
            "path": "/usr/bin/runsc"
        }
    }
}
# 修改后配置:
{
    "runtimes": {
        "runsc": {
            "path": "/usr/bin/runsc"
        }
    },
    "registry-mirrors": ["https://docker.1panel.dev"]
}

重载systemd管理守护进程配置文件

sudo systemctl daemon-reload

重启docker

sudo systemctl restart docker

  1. 运行第一个docker容器

sudo docker run hello-world

分析输出:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
17eec7bbc9d7: Pull complete 
Digest: sha256:f7931603f70e13dbd844253370742c4fc4202d290c80442b2e68706d8f33ce26
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:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
  1. Unable to find image 'hello-world:latest' locally

本地镜像检测,本地镜像没有查找到则需要远程拉取(docker images查找本地镜像)

latest: Pulling from library/hello-world
# 查找到镜像,tag为latest
17eec7bbc9d7: Pull complete
# 分层下载,此处只有一层
Digest: sha256:f7931603f70e13dbd844253370742c4fc4202d290c80442b2e68706d8f33ce26
# SHA256校验保证镜像完整
Status: Downloaded newer image for hello-world:latest
# 镜像成功下载到本地
Hello from Docker!
This message shows that your installation appears to be working correctly. 
# docker安装运行正常

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 #docker-cli和docker守护进程建立了连接
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
    # docker守护进程从Docker Hub拉取了“hello-world”镜像,镜像架构为AMD64
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
    # docker守护进程从镜像创建了容器,执行了现在看到的命令
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.
    # docker守护进程将输出通过流式传输到docker客户端,出现在终端上

Docker Engine:

Docker Engine
Find a comprehensive overview of Docker Engine, including how to install, storage details, networking, and more

Storage

  1. Volume特点 创建 删除docker使用映射和Volume管理数据存储Volume也称卷,是docker用于容器container的持久数据存储由于映射绑定是由宿主机掌握的(/home/jay/Music:/music),如果/home/jay/Music路径改变了,容器就无法读写/home/jay/Music下的数据了,而Volume则由docker管理,这使当然,如果你需要从主机访问添加文件,还是映射绑定更好,举例部署自托管服务Navidrome
    1. 卷比绑定更容易迁移备份
    2. 新卷的内容可以通过容器或构建预先填充
    3. 卷可以在多个容器之间更安全地共享
    4. 可以使用 Docker CLI 命令或 Docker API 管理卷
    5. 有更高的I/O性能

使用映射绑定的yaml文件:

services:
  navidrome:
    image: deluan/navidrome:latest
    user: 1001:1001 # should be owner of volumes
    ports:
      - "4533:4533"
    restart: unless-stopped
    environment:
      # Optional: put your config options customization here. Examples:
      # ND_LOGLEVEL: debug
      - ND_DEFAULTSHAREEXPIRATION=8760h
      - ND_ENABLESHARING=true
      - ND_LASTFM_LANGUAGE=zh
      - ND_LASTFM_APIKEY=XXXXXXXXXXXXX
      - ND_LASTFM_SECRET=XXXXXXXXXXXXX
      - ND_SPOTIFY_ID=XXXXXXXXXXXXX
      - ND_SPOTIFY_SECRET=XXXXXXXXXXXXX
    volumes:
      - "/home/jay/navidrome/data:/data"
      - "/home/jay/Music:/music:ro"

混合映射绑定&卷的yaml文件:

services:
  navidrome:
    image: deluan/navidrome:latest
    user: 1001:1001
    ports:
      - "4533:4533"
    restart: unless-stopped
    environment:
      - ND_DEFAULTSHAREEXPIRATION=8760h
      - ND_ENABLESHARING=true
      - ND_LASTFM_LANGUAGE=zh
      - ND_LASTFM_APIKEY=XXXXXXXXXXXXX
      - ND_LASTFM_SECRET=XXXXXXXXXXXXX
      - ND_SPOTIFY_ID=XXXXXXXXXXXXX
      - ND_SPOTIFY_SECRET=XXXXXXXXXXXXX
    volumes:
      - "navidrome_data:/data"
      - "/home/jay/Music:/music:ro"
      
volumes:
  navidrome_data:
# 手动创建卷
docker volume create navidrome_data

# 查找卷再主机上的路径
docker volume inspect navidrome_data
# [
#     {
#         "CreatedAt": "2025-11-12T11:28:06Z",
#         "Driver": "local",
#         "Labels": null,
#         "Mountpoint": "/var/lib/docker/volumes/navidrome_data/_data",
#         "Name": "navidrome_data",
#         "Options": null,
#         "Scope": "local"
#     }
# ]

# 查看具体权限,默认root权限
sudo ls -la /var/lib/docker/volumes/navidrome_data
# total 12
# drwx-----x  3 root root 4096 Nov 12 11:28 .
# drwx-----x 46 root root 4096 Nov 12 11:28 ..
# drwxr-xr-x  2 root root 4096 Nov 12 11:28 _data

# 通过创建alpine虚拟机来设置数据卷权限,满足yaml文件的1001:1001
docker run --rm -it -v navidrome_data:/data alpine chown 1001:1001 /data
# Unable to find image 'alpine:latest' locally
# latest: Pulling from library/alpine
# 2d35ebdb57d9: Already exists 
# Digest: sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412
# Status: Downloaded newer image for alpine:latest

# 查看具体权限,权限改动完成
sudo ls -la /var/lib/docker/volumes/navidrome_data
# total 12
# drwx-----x  3 root root 4096 Nov 12 11:28 .
# drwx-----x 46 root root 4096 Nov 12 11:28 ..
# drwxr-xr-x  2 jay  jay  4096 Nov 12 11:28 _data

删除Volume

docker volume prune # 删除未使用的卷(谨慎)
docker volume rm navidrome_data # 删除特定的卷,可以通过docker volume list查找volume

Networking

Networking
Learn how networking works from the container’s point of view
  1. docker容器默认启用网络功能,为桥接网络(bridge)
  2. 通过 --network 可以连接到用户自定义网络
# 创建自定义桥接网络
docker network create -d bridge my-net

# 在自定义网络中运行容器
docker run --network=my-net -it busybox
# -it busybox启用终端输出

-d bridge,以及-d host最为常用

驱动程序描述使用场景
bridge默认网络驱动程序单机环境容器通信
host移除容器与主机的网络隔离高性能应用
none完全隔离容器网络安全敏感应用
overlay连接多个 Docker 守护进程Swarm 集群
ipvlan连接到外部 VLAN企业网络集成
macvlan容器作为主机网络设备需要真实 MAC 地址的应用

创建内部网络,容器连接多个网络,设立网关优先级(就像Windows上的接口跃点数)

docker network create --internal my-internal-net 
docker run --network=my-bridge-net --network=my-internal-net my-app # 两个网络,my-app为容器
docker run --network name=gwnet,gw-priority=1 --network anet1 --name myctr myimage # gw-priority=0,优先级最高的网络网关成为默认网关
  1. 端口映射
   ······
    ports:
      - "4533:4533"
    ······

第一个4533:主机上的端口,可以,推荐,最好更改

第二个4533:容器的端口,不推荐更改

端口绑定的访问范围(外网访问,内网访问)

  • 外网可访问(外网可访问,内网可访问,本机可访问,容器间可访问
ports:
  - "4533:4533"

ports:
  - "0.0.0.0:4533:4533"
  • 仅本机访问(外网不可访问,除非使用反向代理,内网不可访问,容器间可访问)
ports:
  - "127.0.0.1:4533:4533"
  • 内网可访问(外网不可访问,除非使用反向代理,本机可能能访问,容器间可访问)
ports:
  - "192.168.1.100:4533:4533" # 本机ip为192.168.1.100就能访问
  • 端口动态绑定(如果要使用NGINX等web服务器实现外网访问,不推荐此做法,除非使用docker网络,nginx处proxy_pass http://navidrome:4533;)适用于开发环境,安全考虑,通过docker的网络反向代理
ports:
  - "4533" # 此为容器端口
  1. 网络管理:
docker network ls
docker network rm XXX-net 
docker network inspect XXX-net # 显示网络详细情况
docker network connect XXX-net XXX-container # 连接运行中的容器到网络
docker network disconnect XXX-net XXX-container # 从网络断开连接

Containers

  1. 容器重启策略
策略 命令示例 描述 适用场景
no --restart no 不自动重启 临时测试
on-failure --restart on-failure 失败时重启 错误恢复
on-failure:5 --restart on-failure:5 限制重启次数 避免无限重启
always --restart always 总是重启 关键服务
unless-stopped --restart unless-stopped 除非手动停止 生产环境

docker-compose.yaml内配置方法(与image、container_name、volumes、ports、environment等同级)

services:
  alist:
    image: 'xhofe/alist:main-aio'
    container_name: alist
    volumes:
      - '/etc/alist:/opt/alist/data'
      - '/home/jay/alist/storage:/opt/alist/storage'
    ports:
      - '5244:5244'
    environment:
      - PUID=1001
      - PGID=1001
      - UMASK=022
    restart: unless-stopped
  1. 部分命令
docker run -d --restart unless-stopped XXX-container
docker run -d --restart on-failure:3 XXX-container
docker stop XXX-container
docker start XXX-container
systemctl restart docker
  1. 进入容器:docker exec
6bfa9714d798   deluan/navidrome:latest                 "/app/navidrome"         6 hours ago   Up 2 hours               0.0.0.0:4533->4533/tcp, [::]:4533->4533/tcp

# 启动bash shell
docker exec -it <容器名或容器ID> /bin/bash
# 使用 sh
docker exec -it <容器名或容器ID> /bin/sh
# 查找(所有:包括停止的)容器
docker ps (-a)
# 退出容器
exit
# 启动容器时进入容器
docker run -it <容器名或容器ID> /bin/bash(sh)
  1. 附加到容器(查看输出)

CLI

Command Line Tools for Container Management | Docker CLI
Simplify Docker container management and monitoring with CLI tools. The Docker CLI allows easy set up through the command line alongside other efficient add-ons.
  1. Docker过滤命令filter
docker COMMAND --filter "KEY=VALUE"
docker COMMAND --filter "KEY!=VALUE"

查找状态为退出的容器 docker ps --filter "status=exited"

以及created, running, paused, restarting, removing, dead

按名称 "name=XXX(navidrome_container)"

按镜像 "ancestor=XXX(nginx)"

按退出码 "exited=0(成功)/1(失败)"

按标签 "label=..."

查找标签:docker inspect <容器名或ID> | grep -A 10 "Labels"

等等

  1. 格式化输出(扩展)利于查看docker输出
docker COMMAND --format '{{模板表达式}}'

常用的格式化函数:

docker inspect <容器/镜像> - 查看详细信息

# 表格输出

# 自定义镜像列表列
docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"
# 自定义容器列表列
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
# 网络列表格式化
docker network ls --format "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.Scope}}"

# JSON格式输出

# 以 JSON 格式输出挂载信息
docker inspect --format '{{json .Mounts}}' container_name
# 输出完整容器信息为 JSON
docker inspect --format '{{json .}}' container_name
# 输出环境变量为 JSON
docker inspect --format '{{json .Config.Env}}' container_name

# join - 连接字符串列表

# 连接容器的启动参数
docker inspect --format '{{join .Args " , "}}' container_name
# 连接环境变量(用换行符)
docker inspect --format '{{join .Config.Env "\n"}}' container_name
# 连接端口绑定信息
docker inspect --format '{{range $p, $conf := .NetworkSettings.Ports}}{{$p}} {{join $conf ","}}{{end}}' container_name

Deamon

  1. Docker 守护进程配置

通过修改JSON配置文件

系统配置 配置文件路径
Linux 常规安装 /etc/docker/daemon.json
Linux Rootless 模式 ~/.config/docker/daemon.json
Windows C:\ProgramData\docker\config\daemon.json
sudo nano /etc/docker/daemon.json
sudo docker info | grep -A 10 "Docker Root Dir" # 输出检测配置语法
sudo systemctl restart docker

检测特定配置项

docker info | grep -i "registry mirror"
docker info | grep -i "storage driver"

验证JSON语法无误

sudo python3 -m json.tool /etc/docker/daemon.json

查看docker详细日志

sudo journalctl -u docker.service -f

查看docker数据存放目录

docker info | grep "Docker Root Dir"

Docker Build

以部署misskey为例

与docker有关的文件

Dockerfile
.dockerignore
compose.local-db.yml
compose_example.yml
  1. Dockerfile:
ARG NODE_VERSION=24.10.0-bookworm
FROM --platform=$BUILDPLATFORM node:${NODE_VERSION} AS native-builder
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
	--mount=type=cache,target=/var/lib/apt,sharing=locked \
	rm -f /etc/apt/apt.conf.d/docker-clean \
	; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache \
	&& apt-get update \
	&& apt-get install -yqq --no-install-recommends \
	build-essential
	
······

ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so
ENV NODE_ENV=production
HEALTHCHECK --interval=5s --retries=20 CMD ["/bin/bash", "/misskey/healthcheck.sh"]
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["pnpm", "run", "migrateandstart"]
  • ARG 构建时参数
  • FROM 选择一个基础镜像作为起点
  • WORKDIR 在容器内创建并进入工作目录
  • COPY 从主机复制文件到镜像内
  • RUN 执行命令,对镜像进行修改
  • ENV 设置环境变量
  • USER 切换运行用户
  • CMD 指定容器启动时运行的默认命令
  • ENTRYPOINT 设置入口点
  • 每个指令创建一个新的镜像层

2..dockerignore

当运行docker build .时,会把整个目录发送给Docker守护进程,包括一些没用的文件.git 日志文件...

.dockerignore告诉Docker构建时候忽略哪些文件,让docker build . 构建快镜像小

.autogen
.github
.travis
.vscode
.config
Dockerfile

......

!.yarn/releases
!.yarn/sdks
!.yarn/versions

.pnpm-store

.idea/
packages/*/.vscode/
packages/backend/test/compose.yml
  1. compose.local-db.yml仅数据库服务
  2. compose_example.yml完整应用栈,修改完后需要改为compose.yml再运行
services:
  web:
    build: .
    restart: always
    links:
      - db
      - redis
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    ports:
      - "3000:3000"
    networks:
      - internal_network
      - external_network
    env_file:
      - .config/docker.env
    volumes:
      - ./files:/misskey/files
      - ./.config:/misskey/.config:ro
  redis:
    restart: always
    image: redis:7-alpine
    networks:
      - internal_network
    volumes:
      - ./redis:/data
    healthcheck:
      test: "redis-cli ping"
      interval: 5s
      retries: 20
  db:
    restart: always
    image: postgres:15-alpine
    networks:
      - internal_network
    env_file:
      - .config/docker.env
    volumes:
      - ./db:/var/lib/postgresql/data
    healthcheck:
      test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
      interval: 5s
      retries: 20
networks:
  internal_network:
    internal: true
  external_network:

开始构建misskey镜像:

  1. git到本地,切换到了 master 分支
git clone -b master https://github.com/misskey-dev/misskey.git
cd misskey
git checkout master
  1. 拉取配置文件的示例文件
cp .config/docker_example.yml .config/default.yml
cp .config/docker_example.env .config/docker.env
cp ./compose_example.yml ./compose.yml

修改三个文件

  1. 构建镜像,数据库设置初始化
sudo docker compose build
sudo docker compose run --rm web pnpm run init

部分docker compose build输出

=> [runner  3/17] COPY ./package.json ./package.json                                               0.1s
 => [runner  4/17] RUN node -e "console.log(JSON.parse(require('node:fs').readFileSync('./package.  4.1s
 => [runner  5/17] WORKDIR /misskey                                                                 0.0s
 => [native-builder 19/22] COPY --link . ./                                                         1.5s
 => [native-builder 20/22] RUN git submodule update --init                                          2.3s
 => [native-builder 21/22] RUN pnpm build                                                          60.0s
 => [runner  6/17] COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./nod  20.4s
 => [runner  7/17] COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/no  0.1s
 => [runner  8/17] COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js  0.0s
 => [runner  9/17] COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-re  0.0s
 => [runner 10/17] COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-bu  0.0s
 => [native-builder 22/22] RUN rm -rf .git/                                                         0.3s
 => [runner 11/17] COPY --chown=misskey:misskey --from=native-builder /misskey/built ./built        1.9s
 => [runner 12/17] COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js  0.0s
 => [runner 13/17] COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-re  0.0s
 => [runner 14/17] COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bu  0.0s
 => [runner 15/17] COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/bu  0.2s
 => [runner 16/17] COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /miss  0.3s
 => [runner 17/17] COPY --chown=misskey:misskey . ./                                                1.1s
 => exporting to image                                                                             18.4s
 => => exporting layers                                                                            18.4s
 => => writing image sha256:77795cb799f1683ac78cb7132c9b97a7103ee7665617789ea10bbbac24a2beb7        0.0s
 => => naming to docker.io/library/misskey-web                                                      0.0s
 => resolving provenance for metadata file                                                          0.0s
[+] Building 1/1
 ✔ misskey-web  Built 

构建成功,输出misskey-web

使用docker images | grep misskey快速查找镜像

docker images | grep misskey
misskey-web   latest  77795cb799f1   6 minutes ago   2.65GB

构建镜像会消耗大量内存与CPU性能

sudo docker compose run --rm web pnpm run init 初始化 Misskey 数据库和设置

--rm为命令执行后自动删除容器

webcompose.yml的服务名称

pnpm run init为在容器内执行的命令

# 初始化 Misskey 数据库和设置
sudo docker compose run --rm web pnpm run init
[+] Running 21/21
 ✔ redis Pulled                                                                                     8.2s # 拉取redis
   ✔ f637881d1138 Pull complete                                                                     3.4s 
······ 
   ✔ d75b3becd998 Pull complete                                                                     5.5s 
 ✔ db Pulled                                                                                        7.8s # 拉取PostgreSQL
   ✔ 2d35ebdb57d9 Already exists                                                                    0.0s 
······
   ✔ 9229d0c336e2 Pull complete                                                                     5.0s 
[+] Creating 4/4
 ✔ Network misskey_internal_network  Created                                                        0.0s # 创建容器内部网络
 ✔ Network misskey_external_network  Created                                                        0.1s # 创建容器外部网络
 ✔ Container misskey-redis-1         Created                                                        0.4s # 创建redis容器
 ✔ Container misskey-db-1            Created                                                        0.4s # 创建postgrespl容器
[+] Running 2/2
 ✔ Container misskey-db-1     Started                                                               0.2s 
 ✔ Container misskey-redis-1  Started                                                               0.3s 

> [email protected] init /misskey

# 后台启动docker容器
docker compose up -d
# 流式输出容器logs
docker compose logs -f
  1. 成功启动,访问ip:port
  1. 将本地镜像迁移到其他服务器

docker save & docker load

准备两台服务器:
目标服务器上运行(ssh端口为55520)

sudo apt install rsync

本服务器上运行:

docker images

misskey-web  latest    77795cb799f1   34 minutes ago   2.65GB
docker compose down

docker save -o misskey.tar misskey-web:latest

# compose.yml内有三个服务:web redis db
# docker save -o misskey.tar misskey-web:latest只会导出web的镜像misskey-web:latest

ls -la misskey.tar 

# -rw------- 1 jay jay 2751643136 Nov 12 14:49 misskey.tar
sudo apt install rsync
rsync -avP -e "ssh -p 55520" misskey.tar [email protected]:~/misskey/

传输成功

目标服务器上:

导入镜像:

docker load -i misskey.tar

docker images

Docker Compose

Start Docker Daemon: Step-by-Step Guide
  • V2: 基于Go语言重写,性能更好,功能更丰富
  • V1: 原始的Python实现,已不再支持

而debian12的默认源使用的就是过时的V1 Compose,启动命令为docker-compose up -d

新版V2 Compose,启动命令为docker compose up -d

Compose从V1的docker二级命令变为V2的模块插件

查看docker compose 版本

docker compose version

Docker Compose version v2.39.4

手动安装Docker Compose插件

DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.40.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose

chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose

将docker run的命令变为docker-compose.yaml格式

相关网站:https://www.composerize.com

docker run -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --restart always --log-opt max-size=1g nginx
version: "3"
services:
    nginx:
        ports:
            - 80:80
        volumes:
            - /var/run/docker.sock:/tmp/docker.sock:ro
        restart: always
        logging:
            options:
                max-size: 1g
        image: nginx

其他容器化/虚拟化学习路径

LXC

Linux Containers - LXC - 介绍
The umbrella project behind Incus, LXC, LXCFS, Distrobuilder and more.

Podman

Podman

Kubernetes

Kubernetes 文档
Kubernetes 是一个开源的容器编排引擎,用来对容器化应用进行自动部署、扩缩和管理。此开源项目由云原生计算基金会(CNCF)托管。

Proxmox

Proxmox Server Solutions
Proxmox develops powerful and efficient open-source server solutions like the Proxmox VE platform, Proxmox Backup Server, and Proxmox Mail Gateway.

参考资料

https://docs.docker.com

https://zh.wikipedia.org/wiki/Docker

https://misskey-hub.net/cn/docs/for-admin/install/guides/docker

https://docker.1panel.dev