Docker Compose 是一个用于界说和运转多容器 Docker 运用程序的东西。
它答运用户经过一个 YAML 文件来装备运用程序的服务,这个文件称为 docker-compose.yml。
运用 Docker Compose,您能够轻松地办理多个 Docker 容器的部署,包含发动、中止和重启服务,以及查看运转状态等。
基本组成
- Services:在 docker-compose.yml 文件中,能够界说多个服务,每个服务都将运转在一个或多个容器中。
- Networks:能够为服务指定网络,以控制容器之间的通讯方式。
- Volumes:能够界说数据卷,以便在容器之间同享数据或耐久化数据。
创立 Nest 引进 mysql 服务
创立 Nest 项目试试:
nest new docker-compose-test -p npm
装置 tyeporm、mysql2:
npm install @nestjs/typeorm typeorm mysql2
在 mysql workbench 里创立个 database:
CREATE DATABASE `test` DEFAULT CHARACTER SET utf8mb4;
在 AppModule 引进 TypeOrmModule:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'xxx',
database: 'test',
synchronize: true,
logging: true,
entities: [],
poolSize: 10,
connectorPackage: 'mysql2',
extra: {
authPlugin: 'sha256_password',
},
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
src 目录下创立 test.entity.ts:
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class Test {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
email: string;
}
在 entities 里注册下:
发动 Nest 服务:
npm run start:dev
mysql 服务没问题。
引进 redis 服务
npm install redis
AppModule 增加一个 redis:
{
provide: 'REDIS_CLIENT',
async useFactory() {
const client = createClient({
socket: {
host: 'localhost',
port: 6379,
},
});
await client.connect();
return client;
},
},
在 AppControll 里注入下:
然后拜访下 http://localhost:3000 后。
服务端打印了 redis 里的 key:
这就阐明 redis 服务也衔接成功了。
没有 docker compose
假设咱们 nest 服务开发完了,想部署,那就要写这样的 dockerfile:
# Step 1: 运用带有 Node.js 的基础镜像
FROM node:18-alpine as builder
# 设置作业目录
WORKDIR /usr/src/app
# 仿制 package.json 和 package-lock.json(假如可用)
COPY package*.json ./
# 装置项目依靠
RUN npm install --only=production
# 装置 nest CLI 东西(保证它作为项目依靠被装置)
RUN npm install @nestjs/cli -g
# 仿制一切文件到容器中
COPY . .
# 构建运用程序
RUN npm run build
# Step 2: 运转时运用更精简的基础镜像
FROM node:18-alpine
# 创立 runc 的符号链接
RUN ln -s /sbin/runc /usr/bin/runc
WORKDIR /usr/src/app
# 从 builder 阶段仿制构建好的文件
COPY --from=builder /usr/src/app/dist ./dist
COPY --from=builder /usr/src/app/node_modules ./node_modules
# 露出 3000 端口
EXPOSE 3000
# 运转 Nest.js 运用程序
CMD ["node", "dist/main"]
由于咱们项目依靠 mysql,redis,所以咱们要先运转 mysql、redis 镜像,最后才能运转 nest 镜像。
咱们运转之后还会报错:
说是 127.0.0.1 的 6379 端口连不上。
注意 nest 容器里需要运用宿主机 ip 来拜访 mysql、redis 服务,所以咱们在 nest 运用里面要把 mysql 和 redis 的 host 全改写宿主机 ip。
终端输入 ifconfig,在 en0 找到自己的 ip。
之后 dockerfile build 一个 nest 镜像,别离按次序运转 mysql、redis 和 nest 镜像即可。
引进 docker compose
**编写 docker-compose.yml 文件:**根目录增加一个 docker-compose.yml,界说服务、网络和数据卷等:
version: '1.0'
# 界说服务,即需要运转的容器集合
services:
# 界说一个名为'nest-app'的服务
nest-app:
# 构建装备,指定Dockerfile的途径和上下文
build:
# 指定Docker构建上下文的途径,通常是Dockerfile所在的目录
context: ./
# 指定Dockerfile的途径,相对于构建上下文
dockerfile: ./Dockerfile
# 界说该服务所依靠的其他服务,它们将按照依靠次序发动
depends_on:
# 依靠名为'mysql-container'的服务
- mysql-container
# 依靠名为'redis-container'的服务
- redis-container
# 端口映射,将宿主机的3000端口映射到容器的3000端口
ports:
- '3000:3000'
# 界说一个名为'mysql-container'的服务,运用mysql镜像
mysql-container:
# 指定运用mysql官方Docker镜像
image: mysql
# 端口映射,将宿主机的3306端口映射到容器的3306端口
ports:
- '3306:3306'
# 数据卷装备,用于耐久化存储
volumes:
# 将宿主机的/Users/yunmu/Desktop/mysql目录映射到容器的/var/lib/mysql目录
- /Users/yunmu/Desktop/mysql:/var/lib/mysql
environment:
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: xxx
# 界说一个名为'redis-container'的服务,运用redis镜像
redis-container:
# 指定运用redis官方Docker镜像
image: redis
# 端口映射,将宿主机的6379端口映射到容器的6379端口
ports:
- '6379:6379'
# 数据卷装备,用于耐久化存储
volumes:
# 将宿主机的/Users/yunmu/Desktop/redis目录映射到容器的/data目录
- /Users/yunmu/Desktop/redis:/data
每个 services 都是一个 docker 容器,名字随意指定。
发动服务 :运转以下指令来发动一切界说的服务:
docker-compose up
它会把一切容器的日志一起输出,先跑的 mysql、redis,再跑的 nest。
也能够运转这个指令:
docker-compose up -d --build --force-recreate
-
-d
:Detached mode,意味着 Docker Compose 会在后台运转容器。 - –
-build
:在发动服务之前强制重构建服务关联的镜像。 -
--force-recreate
:即使容器的装备没有改动,也强制重新创立容器。
成功创立。
浏览器拜访下 http://localhost:3000/:
nest 容器内打印了 redis 的 key。
中止移除 Docker Compose 发动的容器:
docker-compose down
假如还想移除对应的镜像,请运用:
docker-compose down --rmi all
桥接网络
Docker 桥接网络是一种网络形式,答应容器在同一个宿主机上进行通讯,一起与宿主机以及其他未衔接到该桥接网络的容器阻隔。
在 Docker 桥接网络中,每个容器都会被分配一个独立的IP地址,并且这些IP地址都是与宿主机不同的。
Docker 经过桥接器(bridge)将这些容器衔接起来,构成一个虚拟的网络环境。
容器之间能够经过这个网络环境进行通讯,而宿主机也能够经过桥接器与容器进行通讯。
Docker桥接网络适用于在同一个宿主机上运转的容器之间的通讯。假如需要在不同宿主机上的容器之间进行通讯,则能够运用Docker的覆盖网络(overlay network)。
当发动一个Docker容器时,假如没有指定网络形式,那么默许会运用桥接网络。能够经过Docker指令或Docker Compose文件来装备容器的网络形式。
经过 docker network 来创立叫桥接网络:
docker network create common-network
经过 networks 指定创立的 common-network 桥接网络,网络驱动程序指定为 bridge。
其实咱们一向用的网络驱动程序都是 bridge,它的含义是容器的网络和宿主机网络是阻隔开的,可是能够做端口映射。比方 -p 3000:3000、-p 3306:3306 这样。
修改 AppModule 的代码,改成用容器名来拜访:
先删除之前的容器镜像:
docker-compose down --rmi all
运转 compose:
成功运转。
其实不指定 networks 也能够,docker-compose 会创立个默许的:
运转 docker-compose up , 你会发现它创立了一个默许的 network:
所以,不手动指定 networks,也是能够用桥接网络的。
咱们假如不必 docker compose,能够在 docker run 的时分指定 –network,这样 3 个容器经过容器名也能互相拜访。
比方:
docker run -d --network common-network -v /Users/yunmu/Desktop/mysql:/var/lib/mysql --name mysql-container mysql
docker run -d --network common-network -v /Users/yunmu/Desktop/redis:/data --name redis-container redis
docker run -d --network common-network -p 3000:3000 --name nest-container nest-image
其实本质就是对 Network Namespace 的处理,本来是 3 个独立的 Namespace,当指定了 network 桥接网络,就能够在自己 Namespace 下拜访别的 Namespace 了。