Docker中的Compose, 私库 registry,使用私库 Harbor

发布于:2025-07-20 ⋅ 阅读:(13) ⋅ 点赞:(0)

一:Compose 介绍

思考: 现有 docker 进行项目部署存在的问题?

对于现代应用来说,大多都是通过很多的微服务互相协同组成的一个完整应用。

例如,订单管理、用户管理、品类管理、缓存服务、数据库服务等,它们构成了一个电商平台的应用。

而部署和管理大量的服务容器是一件非常繁琐的事情。而 Docker Compose 就是解决这类问题的。

docker 容器提供了一种封装格式,可以将应用和其运行环境封装在一起,但是在线上实践过程中,应用和应用之间难免要产生依赖,一个上游的应用,可能会依赖于下游的一个或者几个应用给其提供数据。

正所谓一个好汉三个帮,现实情况中,一个服务部署完成之后,对外不产生依赖的情况还是比较少的,但是 docker 在开始设计的时候没有过多考虑到容器之间依赖关系的处理。

1、为了完成一个完整项目势必用到N多个容器(一个容器只运行一个进程)配合完成项目中业务开发。

一旦引入N多个容器,容器之间就会形成某种依赖,也就意味某个容器或某些容器的运行需要其他容器优先启动之后才能正常运行。

容器的编排显得至关重要,容器的运行一定要有先后顺序。

2、现在这种方式使用容器,没有办法站在项目的角度将一个项目用到的一组容器划分到一起,日后难点在于项目的多服务器部署。

比如项目在当前服务器上运行成功,需要将项目再部署到另一台服务器上,但我们不清楚哪组容器是项目引用的,哪组容器是别的引用的。

Docker Compose 是一个需要在 Docker 主机上进行安装的 Docker 容器编排外部工具。

其并不是通过脚本或各种冗长的 Docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整个应用,然后通过一条命令完成应用部署。

部署成功后,还可通过一系列简单命令实现对其完整生命周期的管理。

1、Compose 安装

 

注意:只有 Linux 平台上在安装docker时没有安装docker-compose,windows、macos平台安装docker时会自动安装docker-compose。

下载 docker-compose文件:

官网下载地址:

wget https://github.com/docker/compose/releases/download/
v2.36.2/docker-compose-linux-x86_64

 赋予执行权限:

sudo chmod +x /usr/local/bin/docker-compose

使用命令 docker-compose -v 查看 compose 版本:

 

出现版本号说明安装成功

二:Compose 文件内容

2.1、文件简介

Docker Compose 使用 YAML 文件来定义服务。官方推荐的默认文件名为 compose.yml ,但同时也支持 docker-compose.yml。

由于一个 compose 文件中定义的为一个项目的所有服务,所以一般为在创建 compose 文件之前先新建一个目录,目录名称一般为项目名称,然后再将项目所需的所有镜像、微服务的 Dockerfile 放入该目录,并在该目录中新建 compose 文件。

 

docker-compose.yml
│
├── version: '指定文件格式版本'
│   
├── services:
│   │
│   ├── service_name_1:
│   │   ├── build: ./dir_or_dockerfile_details
│   │   ├── image: "镜像名或路径"
│   │   ├── ports:
│   │   │   └── "主机端口:容器端口"
│   │   ├── networks:
│   │   │   └── network_name
│   │   ├── volumes:
│   │   │   └── "/宿主机路径:/容器内路径"
│   │   ├── environment:
│   │   │   └── ["环境变量名=值", ...]
│   │   └── deploy: (仅适用于 Docker Swarm)
│   │       ├── replicas: 数量
│   │       └── mode: 设置模式(global/replicated)
│   │
│   └── service_name_2:
│
├── networks:
│   ├── network_name_1:
│   └── network_name_2:
│
└── volumes:
    ├── volume_name_1:
    └── volume_name_2:

2.2、version

用于指定 Docker Compose 文件格式的版本。不同的版本可能支持不同的特性集。

选择合适的版本可以确保使用到特定的功能或语法。

用于指定当前 docker-compose 文件遵循的规范版本。这决定了哪些功能和配置选项是可用的。

version: '3'
version: '2.4'

从 Docker Compose v2 开始(尤其是 v2.20+),官方已经 不再推荐使用 version: 字段。

因为这个字段现在已经被 Compose CLI 插件自动处理,不再是必须的了。

2.3、services

定义了应用服务的集合。

每个服务都代表了一个容器,这些服务可以通过 Docker Compose 来管理它们的生命周期、网络、存储等。

用于定义一个或多个服务,每个服务对应于一个独立运行的容器。

services:
  web:
    image: "nginx"
services:
  db:
    build: ./dir
(1) build

用于指定一个 Dockerfile 的路径。

而该 Dockerfile 则是用于创建当前服务镜像的。

这个路径可以是以斜杠(/)开头的绝对路径,也可以是相对于当前 compose 文件的、以点(.)号开头的相对路径。

如果 Dockerfile 文件名不是默认名称,则需要通过 build 下的 context 属性指定路径,dockerfile 属性指定文件名。

build: /test
build:
  context: /test
  dockerfile: a.dockerfile
(2)image

用于指定要使用的 Docker 镜像。

这个镜像可以是从本地获取的,也可以是从远程仓库拉取的。

使用已经构建好的镜像能够快速部署服务。

如果使用现成的镜像(通过 image 指定),而不需要从 Dockerfile 构建镜像,那么不需要写 build 这个属性。

image: "ubuntu"
image: "myregistry.com/myapp/myimage:v1"
(3)ports

用于映射端口,使得容器内的服务可以通过主机访问。

这种映射允许外部流量到达容器内部的服务。

ports:
 - "5000:5000"
ports:
 - "8000-8010:9000-9010"
(4)networks

用于定义服务所属的网络。

这允许不同的服务相互通信,同时也控制了服务之间的可见性和隔离性。

networks:
 - some-network
networks:
 - front-tier
 - back-tier
(5)volumes

用于挂载路径作为卷,使得数据持久化或者在不同容器间共享数据。

这种方式对于保存数据库或者其他需要长期保存的数据特别有用。

volumes:
 - /var/lib/mysql:/data
volumes:
 - ./cache:/tmp/cache
(6)environment

用于设置环境变量,可以用来配置应用程序的行为而不必修改代码。

这对于根据不同的部署环境调整配置非常有用。

environment:
  - MYSQL_ROOT_PASSWORD=my-secret-pw
environment:
  POSTGRES_USER: user
  POSTGRES_PASSWORD: pass
(7)deploy

仅适用于使用 docker stack deploy 命令的情况,它配置了服务如何在 swarm 集群中部署。

这包括副本数量、更新策略等高级配置。

deploy:
  replicas: 5
deploy:
  mode: global
(8)depends_on

它确保某些服务在其他服务启动之前已经被启动。

启动顺序:Docker Compose 会按照 depends_on 中指定的顺序来启动服务。

不等待就绪状态:仅保证被依赖的服务先启动,但不会等待该服务的应用程序完全就绪(如数据库服务完全初始化完成)。

这意味着如果一个服务依赖于另一个服务的数据准备情况,需要使用其他机制来确保服务间的正确性,比如健康检查或自定义脚本。

version: '3'
services:
  web:
    build: .
    depends_on:
      - db
    ports:
      - "80:80"
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: example

2.4、volumes

volumes 元素用于定义 Docker 卷。

使用卷可以让你的数据持久化,并且可以在多个容器之间共享或重用这些数据。

此外,卷还可以帮助你绕过 Union File System 的文件系统层限制,从而提高性能。

version: '3'
services:
  db:
    image: "mysql:5.7"
    volumes:
      - db-data:/var/lib/mysql
volumes:
  db-data: # 命名卷

这里我们定义了一个名为 db-data 的命名卷,并将其挂载到容器的 /var/lib/mysql 路径下。

2.5、networks

networks 元素用于定义自定义网络,使得服务能够通过网络相互通信。

默认情况下,Docker Compose 自动创建一个网络来允许你的服务互相通信,在这种情况下,所有服务都将加入到默认网络中,并且可以通过服务名称相互访问。

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
networks:
  default:

但是有时可能想要更多控制或者创建多个隔离的网络。

version: '3'
services:
  proxy:
    build: ./proxy
    networks:
      - frontend
  app:
    build: ./app
    networks:
      - frontend
      - backend
  db:
    image: "mysql:5.7"
    networks:
      - backend

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

三:Compose 命令

3.1、常用命令

services:
  web1:
    image: nginx:latest
    container_name: web1
    ports:
      - "8080:80"
    volumes:
      - ./web1/html:/usr/share/nginx/html
    networks:
      - app-network
  web2:
    image: nginx:latest
    container_name: web2
    ports:
      - "8081:80"
    volumes:
      - ./web2/html:/usr/share/nginx/html
    networks:
      - app-network
  db1:
    image: mysql:8.0
    container_name: db1
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    ports:
      - "3306:3306"
    volumes:
      - db1_data:/var/lib/mysql
    networks:
      - app-network
  db2:
    image: mysql:8.0
    container_name: db2
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    ports:
      - "3307:3306"
    volumes:
      - db2_data:/var/lib/mysql
    networks:
      - app-network
volumes:
  db1_data:
  db2_data:
networks:
  app-network:
    driver: bridge

构建(或重新构建)服务

构建或重建服务,使用 Dockerfile 中指定的内容。

docker-compose build

Docker Compose 会根据 docker-compose.yml 文件中定义的每个服务(service)里包含的 build 配置项,逐个构建对应的服务镜像。

创建并启动容器

docker-compose up

使用 docker-compose.yml 文件中的配置创建并启动所有服务。加上 -d 参数可以在后台运行。

docker-compose up -d

停止服务

docker-compose stop

停止正在运行的服务而不删除它们。

停止并移除容器、网络

docker-compose down

停止并移除由 docker-compose.yml 定义的所有容器、网络以及默认情况下不会移除卷。

查看服务状态

docker-compose ps

显示由 docker-compose.yml 文件定义的所有服务的状态。

列出镜像

docker-compose images

列出 Compose 文件中服务使用的镜像。

3.2、日志相关命令

查看服务日志

docker-compose logs <服务名>

显示由 docker-compose.yml 文件定义的所有服务的日志输出。加上 -f 参数可以实时跟踪日志更新。

docker-compose logs -f

3.3、运行一次性命令

运行一次性命令

docker-compose run [SERVICE] [COMMAND]

在服务的容器内执行一个命令。这对于调试非常有用。

docker-compose run web bash

3.4、网络与卷管理

创建网络

docker-compose create

只创建网络和卷,但不启动服务。

重启服务

docker-compose restart

重启服务。

3.5、高级命令

拉取服务镜像

docker-compose pull

拉取服务依赖的所有镜像。

执行命令

docker-compose exec [SERVICE] [COMMAND]

进入正在运行的服务容器,并执行命令。这类似于 docker exec 命令。

示例:

docker-compose exec web sh

检查配置

docker-compose config

验证并查看 docker-compose.yml 文件的有效配置。

指定文件:使用 -f 参数指定不同的 Compose 文件名。

docker-compose -f alternate-compose.yml up

四:配置一主两从架构

services:
  master:
    image: mysql:8.0
    container_name: mysql_master
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - /data/mysql/master/conf/my.cnf:/etc/my.cnf
      - /data/mysql/master/data:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - mysql-network

  slave1:
    image: mysql:8.0
    container_name: mysql_slave1
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - /data/mysql/slave1/conf/my.cnf:/etc/my.cnf
      - /data/mysql/slave1/data:/var/lib/mysql
    ports:
      - "3307:3306"
    depends_on:
      - master
    networks:
      - mysql-network

  slave2:
    image: mysql:8.0
    container_name: mysql_slave2
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - /data/mysql/slave2/conf/my.cnf:/etc/my.cnf
      - /data/mysql/slave2/data:/var/lib/mysql
    ports:
      - "3308:3306"
    depends_on:
      - master
    networks:
      - mysql-network

networks:
  mysql-network:
    driver: bridge

使用 Docker Compose 只是创建并启动了容器,并不会自动执行 MySQL 主从复制相关的配置命令。

容器层面(由 Docker Compose 完成)

操作 是否 Docker Compose 可完成
创建主从容器 ✅ 是
挂载数据目录和配置文件 ✅ 是
设置环境变量 ✅ 是
定义网络互通 ✅ 是

数据库层面(需要手动完成)

操作 是否 Docker Compose 可完成
在主服务器上启用 binlog ❌ 否(需改 my.cnf)
创建主从复制专用账号 ❌ 否(需执行 SQL)
在从服务器上设置 server-id ❌ 否(需改 my.cnf)
执行 CHANGE MASTER TO ... 命令 ❌ 否(需执行 SQL)
启动复制线程 START SLAVE; ❌ 否(需执行 SQL)

如果希望能自动化如何做?

MySQL 官方镜像支持一个非常有用的机制:

如果在容器启动前将 .sql.sh 文件放到 /docker-entrypoint-initdb.d/ 目录下,容器会在第一次启动时自动执行这些文件中的内容。

当容器启动时,只有在数据目录为空的情况下,才会执行 /docker-entrypoint-initdb.d/ 目录下的 .sql.sh 文件。

init-master.sql

CREATE USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';

FLUSH PRIVILEGES;

init-slave.sql

STOP SLAVE;

RESET SLAVE ALL;

CHANGE MASTER TO
  MASTER_HOST='master',
  MASTER_USER='slave',
  MASTER_PASSWORD='123456',
  MASTER_AUTO_POSITION = 1;

START SLAVE;

SHOW SLAVE STATUS\G;
mysql
    ├── conf
    │   └── my.cnf
    ├── master
    │   ├── conf
    │   │   └── my.cnf
    │   ├── data
    │   └── sql
    │       └── init-master.sql
    ├── slave1
    │   ├── conf
    │   │   └── my.cnf
    │   ├── data
    │   └── sql
    │       └── init-slave.sql
    └── slave2
        ├── conf
        │   └── my.cnf
        ├── data
        └── sql
            └── init-slave.sql
services:
  mysql_master:
    image: mysql:8.0
    container_name: mysql_master
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - /data/mysql/master/data:/var/lib/mysql
      - /data/mysql/master/conf/my.cnf:/etc/my.cnf
      - /data/mysql/master/sql/init-master.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "3306:3306"
    networks:
      - mysql-network

  mysql_slave1:
    image: mysql:8.0
    container_name: mysql_slave1
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - /data/mysql/slave1/data:/var/lib/mysql
      - /data/mysql/slave1/conf/my.cnf:/etc/my.cnf
      - /data/mysql/slave1/sql/init-slave.sql:/docker-entrypoint-initdb.d/init-slave.sql
    ports:
      - "3307:3306"
    depends_on:
      - mysql_master
    networks:
      - mysql-network

  mysql_slave2:
    image: mysql:8.0
    container_name: mysql_slave2
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - /data/mysql/slave2/data:/var/lib/mysql
      - /data/mysql/slave2/conf/my.cnf:/etc/my.cnf
      - /data/mysql/slave2/sql/init-slave.sql:/docker-entrypoint-initdb.d/init-slave.sql
    ports:
      - "3308:3306"
    depends_on:
      - mysql_master
    networks:
      - mysql-network

networks:
  mysql-network:
    driver: bridge

五:配置nginx与后端集群

我们使用 Docker Compose 来实现以下架构:

  • 1 个 Nginx 容器:负责反向代理和负载均衡;

  • 3 个 Java 后端服务容器(backend1, backend2, backend3);

  • 所有服务都在同一个自定义 Docker 网络中通信;

  • 不需要构建自定义 Nginx 镜像,直接使用官方镜像 + 挂载配置文件;

  • 使用 openjdk:8 构建后端服务镜像。

project/
├── dockerfile
├── html
├── java
│   └── msg.jar
└── nginx
    └── default.conf
upstream tomcatList {
    server backend1:8081 weight=1;
    server backend2:8081 weight=1;
    server backend3:8081 weight=1;
}

server {

    listen  80;
    server_name  localhost;

    location / {
        root   /etc/nginx/html/;
        index  index.html index.htm;
    }

    location ~^/api/ {
        rewrite ^/api/(.*)$ /$1 break;
        proxy_pass  http://tomcatList;
        proxy_redirect default;
    }

}

建立html文件夹并放入对应页面,并构建对应的dockerfile

FROM openjdk:8-jdk-alpine

WORKDIR /app

COPY ./java/msg.jar app.jar

EXPOSE 8081

ENTRYPOINT ["java", "-jar", "app.jar"]

编写docker-compose.yml

services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
    volumes:
      - /test/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - /test/html:/etc/nginx/html
    depends_on:
      - backend1
      - backend2
      - backend3
    networks:
      - app-network

  backend1:
    build:
      context: .
      dockerfile: dockerfile
    container_name: backend1
    networks:
      - app-network

  backend2:
    build:
      context: .
      dockerfile: dockerfile
    container_name: backend2
    networks:
      - app-network

  backend3:
    build:
      context: . 
      dockerfile: dockerfile
    container_name: backend3
    networks:
      - app-network

networks:
  app-network:
    driver: bridge	

六:compose重启策略

Docker Compose 支持几种不同的重启策略,可以根据的需求选择合适的策略。

常用的重启策略

  • no:默认策略,不自动重启容器。

  • always:无论退出状态如何,总是尝试重启容器。如果 Docker 守护进程重启,也会尝试重启容器。

  • on-failure:仅当容器以非零退出代码终止时才重启容器。可以指定最大重试次数,例如 on-failure:5

  • unless-stopped:总是重启容器,除非容器被手动停止(使用 docker stop 或通过 Docker API 停止)。

 

services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
    volumes:
      - /data/project/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - /data/project/html:/etc/nginx/html
    depends_on:
      - backend1
      - backend2
      - backend3
    networks:
      - app-network
    restart: always  # 设置重启策略

  backend1:
    build:
      context: .
      dockerfile: java.Dockerfile
    container_name: backend1
    expose:
      - "8081"
    networks:
      - app-network
    restart: unless-stopped  # 另一种重启策略

  backend2:
    build:
      context: .
      dockerfile: java.Dockerfile
    container_name: backend2
    expose:
      - "8081"
    networks:
      - app-network
    restart: unless-stopped

  backend3:
    build:
      context: . 
      dockerfile: java.Dockerfile
    container_name: backend3
    expose:
      - "8081"
    networks:
      - app-network
    restart: unless-stopped

networks:
  app-network:
    driver: bridge

七:使用私库 registry

设置私有仓库

使用 Docker Registry 来搭建私有仓库:

docker run -d -p 5000:5000 --restart=always --name my-registry registry

标记镜像并上传至私有仓库

给镜像打标签以便推送到指定仓库:

docker tag my-custom-image:1.0 localhost:5000/my-custom-image:1.0

 将镜像推送到私有仓库:

docker push localhost:5000/my-custom-image:1.0

从私有仓库下载镜像

下载存储在私有仓库中的镜像:

docker pull localhost:5000/my-custom-image:1.0

八:使用私库 Harbor

8.1、使用 Harbor

前往 Harbor GitHub Releases 页面 下载最新版本。

# 下载 v2.11.0 在线安装包
wget https://github.com/goharbor/harbor/releases/download/v2.11.0/harbor-online-installer-v2.11.0.tgz

解压并配置 Harbor

tar xvf harbor-online-installer-v2.11.0.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
vim harbor.yml

修改 harbor.yml 文件中的以下字段:

hostname: 192.168.66.146  # 替换为你的域名或IP地址
http:
  port: 80
# 如果需要 HTTPS:
# https:
#   port: 443
#   certificate: /your/cert/path.crt
#   private_key: /your/cert/private.key

安装 Harbor

./install.sh

等待几分钟,Harbor 将启动成功。

本质是构建了多个docker容器。要注意别删掉了

访问浏览器:

http://192.168.66.146

默认账号密码:

  • 用户名:admin

  • 密码:Harbor12345

功能 描述
项目管理 可创建多个项目(Project),隔离不同团队/应用的镜像
角色权限控制 支持项目管理员、开发者、访客等角色
镜像扫描 集成 Clair 等工具检测漏洞
Webhook 镜像上传后触发通知或 CI/CD 流程
复制策略 多个 Harbor 实例之间同步镜像
内容信任(Notary) 签名镜像,防止篡改

8.2、推送至 Harbor

登录 Harbor

docker login 192.168.66.146
# 输入用户名和密码(如 admin / Harbor12345)

如果你使用的是 HTTP 而不是 HTTPS,需要在 Docker daemon.json 中添加 insecure-registries:

{
  "insecure-registries" : ["192.168.66.146"]
}

然后重启 Docker:

systemctl restart docker

构建本地镜像

例如有一个简单的 Java 应用镜像:

docker build -t 192.168.66.146/library/my-java-app:1.0 .

注意:library 是默认项目名,也可以替换为你创建的其他项目(Project)

推送镜像到 Harbor

docker push 192.168.66.146/library/my-java-app:1.0

刷新 Harbor 页面,你应该能看到刚刚上传的镜像。

8.3、拉取镜像

在另一台机器上(已登录 Harbor):

docker pull 192.168.66.146/library/my-java-app:1.0

然后运行:

docker run -d --name myapp 192.168.66.146/library/my-java-app:1.0
对比项 Docker Registry Harbor
图形界面
权限控制 简单 强大
安全扫描 不支持 支持
Webhook/通知 不支持 支持
易用性 简单轻量 相对复杂但功能强大
适合场景 临时测试环境 生产环境、企业级使用

九:容器重启策略

如果你希望某些容器在 Docker 守护进程启动时自动运行,可以使用 --restart 策略。

这个策略告诉 Docker 当容器退出时应该如何处理它们,包括当 Docker 守护进程重启时的行为。

  • no:默认值,不自动重启容器。

  • on-failure:仅在容器退出状态码非0时重启。

  • always:无论退出代码是什么,总是重启容器(包括 Docker 守护进程重启后)。

  • unless-stopped:总是重启容器,除非它被手动停止。

例如,要确保一个名为 my_service 的容器始终运行,即使 Docker 守护进程重启了,可以这样运行容器:

docker run -d --restart unless-stopped --name my_service my_image

 


网站公告

今日签到

点亮在社区的每一天
去签到