1. 介绍

本文将会使用一个叫 Docker Compose 的工具,他是建立在 Docker引擎之上的,它使得启动包含多个容器的应用变得非常容易快捷。

2. 安装Docker Compose

官方的安装说明文档 https://docs.docker.com/compose/install

如果你使用的是Windows或Mac os的Docker Desktop App,

Docker Compose已经被集成在内无需额外安装。

如果你不确定可以在终端输入如下命令来验证是否有安装

docker compose --version

下面将会展示如何在Debian / Ubuntu 安装 Docker Compose

sudo apt-get update
sudo apt-get install docker-compose-plugin

通过检查版本来验证 Docker Compose 是否正确安装。

docker compose --version

预期输出:

Docker Compose version vN.N.N

3. 技巧分享

在我们开始之前我想向你展示一些清理工作区的技巧

docker images    #列出镜像
docker ps    #列出正在运行的容器

假设我想要把他们全部删除我应该怎么做呢?

我们可以使用 docker image rm 镜像ID 命令来删除一个或多个镜像,那么我们如何获取所有的镜像ID并传到这个命令中呢?

运行 docker image ls 命令列出所有的镜像,加上参数 -q 我们就只会见到所有的镜像ID ,现在我们可以将它作为参数传递给上面的删除镜像命令。

docker image rm $(docker image ls -q)

如果我们执行这个命令可能会报错,因为有些镜像是正在运行的容器又或者是已停止的容器,所以我们需要先删除容器先,我们可以用一样的技巧来实现。

docker container rm $(docker container ls -aq)

这条命令的作用就是获取所有的(包括已停止的)容器ID删除容器的命令执行 ,

当你尝试这条命令你还是有可能会因为有容器在运行中导致报错,让我们加上参数 -f 来强制执行,

docker container rm -f $(docker container ls -aq)

执行完成上面的命令所有的容器就已经删除干净了,接下来让我们删除镜像

docker image rm -f $(docker image ls -aq)

ok,让我们来验证一下

docker ps -a    #列出所有的容器(包括已停止的)
docker images    #列出所有镜像

好的现在我们有个干净的工作区啦ww

4. 示例

正如前言所说Docker Compose让启动包含多个容器的应用变成异常简单

举个例子,我现在有个应用包括了三个服务,一个后端一个前端以及一个数据库。

假设我们没有Docker我们要如何做?

是不是要非常痛苦的一个个搭建不同服务依赖的环境,还有复杂的调试。

但是有Docker情况就不一样了,上面这些我们都不需要做,

我只需要执行一个命令就可以了,下面让我来用一个docker项目演示一下

首先我们新建一个项目文件夹(为什么要这么做我稍后解释)

mkdir -p data/docker_data/umami

创建 compose.yaml 文件

touch compose.yaml

使用nano或者vim编辑文件

---
version: '3'
  services:
    umami:
      image: docker.umami.dev/umami-software/umami:postgresql-latest
      ports:
        - "3001:3000"    #冒号左边的可以改本例构建完成后可使用ip:3001访问服务
      environment:
        DATABASE_URL: postgresql://umami:umami@db:5432/umami
        DATABASE_TYPE: postgresql
        APP_SECRET: replace-me-with-a-random-string    #这里自己编一串字符为密钥如:vm8kngANJ8rh
      depends_on:
        - db
      restart: always
    db:
      image: postgres:15-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - ./sql/schema.postgresql.sql:/docker-entrypoint-initdb.d/schema.postgresql.sql:ro
      - ./umami-db-data:/var/lib/postgresql/data
    restart: always

下面我简单描述一下这个文件的各项细节

0.声明文件类型(这个用于表示这是个yaml文件)

---

1.文件版本(version)

Compose 文件需要指定版本,不同版本支持的功能有所差异。目前较常用的是版本 3,以下是本例:

version: '3'

2.服务定义(service)

services 部分用于定义应用程序中的各个服务,每个服务对应一个容器。以下是本例:

  services:
    umami:
      image: docker.umami.dev/umami-software/umami:postgresql-latest
      ports:
        - "3001:3000"    #冒号左边的可以改本例构建完成后可使用ip:3001访问服务
      environment:
        DATABASE_URL: postgresql://umami:umami@db:5432/umami
        DATABASE_TYPE: postgresql
        APP_SECRET: replace-me-with-a-random-string    #这里自己编一串字符为密钥如:vm8kngANJ8rh
      depends_on:
        - db
      restart: always
    db:
      image: postgres:15-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - ./sql/schema.postgresql.sql:/docker-entrypoint-initdb.d/schema.postgresql.sql:ro
      - ./umami-db-data:/var/lib/postgresql/data
    restart: always

services: 定义了一个名为 umami 的服务 还有一个名为 db 的服务

我们先来说第一个umami 服务

image: 使用 umami:postgresql-latest 镜像,

ports: 将容器的3000端口映射到主机的3001端口,

environment: 设置容器的环境变量

depends_on: 定义服务之间的依赖关系,确保在启动当前服务之前,依赖的服务已经启动。

restart: 定义平台在容器终止时应用的策略,这里是始终重启容器,直到将其删除。

好现在来说 db 服务

image: 使用 postgres:15-alpine 镜像,

environment: 设置容器的环境变量

volumes: 数据卷定义,冒号左边的是主机路径右边的是挂载到db服务的路径

至于其他的Docker Compose 文件的编写规范大家可以啃一下官方文档

https://github.com/compose-spec/compose-spec/blob/main/03-compose-file.md

ok,至此我们完成了compose.yaml 文件的编写,让我们上线容器!

docker compose up -d #-d是后台运行

此时,访问 http://ip:3000 就可以访问了,打开的是英文界面,右上方可以切换语言,默认用户名为admin,密码为umami

如果无法正常访问检查你的防火墙,放行3001端口。

如果要反向代理,且反向代理的服务与umami在一台服务器上,可以不用放行3001端口做好反向代理的设置就好qwq。

5. 总结

大家可以发现我使用的都是相对路径,文件是挂载在项目文件夹的。

我之所以坚持这么做是因为假设有一天你需要迁移服务,你所有的文件都在项目文件夹里面。

docker compose很好的一点是你不需要记长长的docker命令,

迁移服务只需要复制走文件夹,然后一条命令,你的服务就上线了,巨方便。

以上就是本文的全部内容了,希望可以帮助到你,也欢迎大家在下方评论区一起来讨论。

这里是Nicholas Hao,每天进步一点点,让我们下次见 ~~~ See ya ~~~