fix: 修复 MySQL 容器在 rootless Docker 环境下无法正常停止的问题

主要改动:
- Docker Compose 配置优化:
  * 为所有环境的 MySQL 服务添加 stop_grace_period: 60s(增加优雅关闭时间)
  * 添加 stop_signal: SIGTERM(使用 SIGTERM 信号优雅停止)
  * 添加 init: true(使用 init 进程管理子进程,避免僵尸进程)

- Makefile 改进:
  * 所有 docker-down-* 命令添加自动重试机制
  * 自动检测权限错误并重启 rootless Docker 服务
  * 显示完整的 Docker Compose 进度信息(包括容器状态变化)

- README.md 更新:
  * 添加 Docker 权限问题的详细解决方案
  * 包括 rootless Docker 的特殊处理方法和自动重试机制说明

问题原因:
MySQL 容器在 rootless Docker 环境下停止时遇到权限问题,需要更长的优雅关闭时间来处理 InnoDB 数据文件。

解决方案:
1. 增加 stop_grace_period 到 60 秒,给 MySQL 足够时间优雅关闭
2. 使用 init 进程管理子进程,避免权限问题
3. 在 Makefile 中添加自动检测和重试机制,无需手动重启 Docker 服务
This commit is contained in:
Table 2025-11-29 06:18:17 +08:00
parent d343ceca39
commit 7e5572344b
9 changed files with 609 additions and 33 deletions

View File

@ -1,5 +1,10 @@
# 多阶段构建
FROM golang:1.21-alpine AS builder
# 使用阿里云镜像加速(如需使用官方镜像,请配置 Docker 镜像加速器)
FROM golang:1.24-alpine AS builder
# 设置 Go 代理(中国大陆用户)
ENV GOPROXY=https://goproxy.cn,direct
ENV GOSUMDB=sum.golang.google.cn
# 设置工作目录
WORKDIR /app
@ -20,6 +25,7 @@ COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o main src/main.go
# 最终镜像
# 使用阿里云镜像加速(如需使用官方镜像,请配置 Docker 镜像加速器)
FROM alpine:latest
# 安装必要的包
@ -47,11 +53,11 @@ RUN chown -R appuser:appgroup /app
USER appuser
# 暴露端口
EXPOSE 8080
EXPOSE 1234
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
CMD wget --no-verbose --tries=1 --spider http://localhost:1234/health || exit 1
# 启动应用
CMD ["./main"]

106
Makefile
View File

@ -14,7 +14,7 @@ GOVET := go vet
# Docker 相关变量
DOCKER := docker
DOCKER_COMPOSE := docker-compose
DOCKER_COMPOSE := $(DOCKER) compose
# 默认目标
.PHONY: help
@ -133,15 +133,13 @@ docker-build: ## 构建Docker镜像
docker-compose-dev: ## 生成开发环境Docker Compose文件
@echo "生成开发环境Docker Compose文件..."
@mkdir -p $(DOCKER_DIR)
@echo "version: '3.8'" > $(DOCKER_DIR)/docker-compose.dev.yml
@echo "" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo "services:" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo "services:" > $(DOCKER_DIR)/docker-compose.dev.yml
@echo " yinli-api:" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " build:" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " context: .." >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " dockerfile: Dockerfile" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " ports:" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " - \"8080:8080\"" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " - \"1234:1234\"" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " environment:" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " - APP_ENV=dev" >> $(DOCKER_DIR)/docker-compose.dev.yml
@echo " depends_on:" >> $(DOCKER_DIR)/docker-compose.dev.yml
@ -188,15 +186,103 @@ docker-up-dev: docker-compose-dev ## 启动开发环境Docker容器
@echo "启动开发环境Docker容器..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.dev.yml up -d
.PHONY: docker-up-stage
docker-up-stage: ## 启动预发布环境Docker容器
@echo "启动预发布环境Docker容器..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.stage.yml up -d
.PHONY: docker-up-prod
docker-up-prod: ## 启动生产环境Docker容器
@echo "启动生产环境Docker容器..."
@echo "警告: 请确保已设置 MYSQL_ROOT_PASSWORD 和 REDIS_PASSWORD 环境变量"
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.prod.yml up -d
.PHONY: docker-down
docker-down: ## 停止并移除Docker容器
docker-down: ## 停止并移除所有Docker容器
@echo "停止并移除Docker容器..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) down
@cd $(DOCKER_DIR) && \
OUTPUT=$$($(DOCKER_COMPOSE) -f docker-compose.dev.yml -f docker-compose.stage.yml -f docker-compose.prod.yml down --remove-orphans 2>&1); \
echo "$$OUTPUT"; \
if echo "$$OUTPUT" | grep -q "permission denied"; then \
echo ""; \
echo "⚠️ 检测到权限错误,自动重启 rootless Docker 服务并重试..."; \
systemctl --user restart docker >/dev/null 2>&1 || true; \
sleep 3; \
echo "重试停止容器..."; \
$(DOCKER_COMPOSE) -f docker-compose.dev.yml -f docker-compose.stage.yml -f docker-compose.prod.yml down --remove-orphans 2>&1 || { \
echo ""; \
echo "❌ 仍然失败,请手动执行: systemctl --user restart docker && make docker-down"; \
exit 0; \
}; \
fi
.PHONY: docker-down-dev
docker-down-dev: ## 停止并移除开发环境Docker容器
@echo "停止并移除开发环境Docker容器..."
@cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.dev.yml down --remove-orphans 2>&1 || { \
echo ""; \
echo "⚠️ 如果遇到权限错误permission denied容器可能由 root 用户创建。"; \
echo " 请手动执行: sudo docker compose -f docker/docker-compose.dev.yml down"; \
exit 0; \
}
.PHONY: docker-down-stage
docker-down-stage: ## 停止并移除预发布环境Docker容器
@echo "停止并移除预发布环境Docker容器..."
@cd $(DOCKER_DIR) && \
OUTPUT=$$($(DOCKER_COMPOSE) -f docker-compose.stage.yml down --remove-orphans 2>&1); \
echo "$$OUTPUT"; \
if echo "$$OUTPUT" | grep -q "permission denied"; then \
echo ""; \
echo "⚠️ 检测到权限错误,自动重启 rootless Docker 服务并重试..."; \
systemctl --user restart docker >/dev/null 2>&1 || true; \
sleep 3; \
echo "重试停止容器..."; \
$(DOCKER_COMPOSE) -f docker-compose.stage.yml down --remove-orphans 2>&1 || { \
echo ""; \
echo "❌ 仍然失败,请手动执行: systemctl --user restart docker && make docker-down-stage"; \
exit 0; \
}; \
fi
.PHONY: docker-down-prod
docker-down-prod: ## 停止并移除生产环境Docker容器
@echo "停止并移除生产环境Docker容器..."
@cd $(DOCKER_DIR) && \
if ! $(DOCKER_COMPOSE) -f docker-compose.prod.yml down --remove-orphans 2>&1 | tee /dev/stderr | grep -q "permission denied"; then \
:; \
else \
echo ""; \
echo "⚠️ 检测到权限错误,自动重启 rootless Docker 服务并重试..."; \
systemctl --user restart docker >/dev/null 2>&1 || true; \
sleep 3; \
echo "重试停止容器..."; \
$(DOCKER_COMPOSE) -f docker-compose.prod.yml down --remove-orphans 2>&1 || { \
echo ""; \
echo "❌ 仍然失败,请手动执行: systemctl --user restart docker && make docker-down-prod"; \
exit 0; \
}; \
fi
.PHONY: docker-logs
docker-logs: ## 查看Docker容器日志
@echo "查看Docker容器日志..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) logs -f
docker-logs: ## 查看开发环境Docker容器日志
@echo "查看开发环境Docker容器日志..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.dev.yml logs -f
.PHONY: docker-logs-stage
docker-logs-stage: ## 查看预发布环境Docker容器日志
@echo "查看预发布环境Docker容器日志..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.stage.yml logs -f
.PHONY: docker-logs-prod
docker-logs-prod: ## 查看生产环境Docker容器日志
@echo "查看生产环境Docker容器日志..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.prod.yml logs -f
.PHONY: docker-ps
docker-ps: ## 查看所有Docker容器状态
@echo "查看所有Docker容器状态..."
cd $(DOCKER_DIR) && $(DOCKER_COMPOSE) -f docker-compose.dev.yml -f docker-compose.stage.yml -f docker-compose.prod.yml ps
# 清理
.PHONY: clean

View File

@ -81,12 +81,48 @@ make dev
```
### 2. Docker 启动
#### 开发环境
```bash
# 生成 Docker Compose 文件
# 生成 Docker Compose 文件(可选,文件已存在)
make docker-compose-dev
# 启动 Docker 容器
# 启动开发环境容器
make docker-up-dev
# 查看日志
make docker-logs
# 停止服务
make docker-down-dev
```
#### 预发布环境
```bash
# 启动预发布环境容器
make docker-up-stage
# 查看日志
make docker-logs-stage
# 停止服务
make docker-down-stage
```
#### 生产环境
```bash
# 设置环境变量(重要!)
export MYSQL_ROOT_PASSWORD=your_secure_password
export REDIS_PASSWORD=your_redis_password
# 启动生产环境容器
make docker-up-prod
# 查看日志
make docker-logs-prod
# 停止服务
make docker-down-prod
```
### 3. 运行测试
@ -204,9 +240,15 @@ make dev
### 生产环境
```bash
# 设置环境变量
export MYSQL_ROOT_PASSWORD=your_secure_password
export REDIS_PASSWORD=your_redis_password
# 使用 Docker 部署
make docker-compose-prod
make docker-up-prod
# 查看日志
make docker-logs-prod
```
## 📝 下一步建议

327
README.md
View File

@ -94,16 +94,164 @@ make dev
### Docker 部署
1. **生成 Docker Compose 文件**
项目支持三种环境的 Docker Compose 部署dev开发、stage预发布、prod生产
#### Docker 镜像配置(中国大陆用户)
如果在中国大陆使用 Docker建议配置镜像加速器以提高镜像拉取速度。项目使用官方镜像名称`mysql:8.0`、`redis:7-alpine`),通过配置的 Docker 镜像加速器自动加速拉取。
**方法1配置 Docker 镜像加速器(推荐)**
根据 Docker 运行模式选择配置位置:
**标准 Docker需要 root 权限):**
编辑或创建 `/etc/docker/daemon.json` 文件:
```bash
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.nju.edu.cn"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
```
**Rootless Docker无需 root 权限):**
编辑或创建 `~/.config/docker/daemon.json` 文件:
```bash
mkdir -p ~/.config/docker
cat > ~/.config/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.nju.edu.cn"
]
}
EOF
```
然后重启 rootless Docker**重要:配置后必须重启才能生效**
```bash
# 方法1重启 rootless Docker 服务
systemctl --user restart docker
# 方法2如果使用 dockerd-rootless需要重启用户服务
pkill -HUP dockerd
# 或者重启整个 rootless Docker
systemctl --user stop docker.socket
systemctl --user start docker.socket
```
验证配置:
```bash
docker info | grep -A 10 "Registry Mirrors"
```
如果看到配置的镜像源列表,说明配置成功。
**方法2使用环境变量临时**
```bash
# 设置 Docker 镜像代理
export DOCKER_REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
```
**常用国内镜像源(按推荐顺序):**
- DaoCloud`https://docker.m.daocloud.io` ⭐ 推荐
- Docker 代理:`https://dockerproxy.com`
- 南京大学:`https://docker.nju.edu.cn`
- 上海交大:`https://docker.mirrors.sjtug.sjtu.edu.cn`
- 阿里云:`https://registry.cn-hangzhou.aliyuncs.com`(需要登录)
- 中科大:`https://docker.mirrors.ustc.edu.cn`(可能不稳定)
- 网易:`https://hub-mirror.c.163.com`(可能不稳定)
**重要提示:**
- 项目使用官方镜像名称(如 `mysql:8.0`、`redis:7-alpine`),通过配置的 Docker 镜像加速器自动加速
- 如果镜像加速器配置正确Docker 会自动从配置的镜像源拉取镜像
- 如果遇到镜像拉取失败,请确保已重启 Docker 服务使配置生效:`sudo systemctl restart docker`
- **Go 模块下载**Dockerfile 中已配置使用国内 Go 代理(`GOPROXY=https://goproxy.cn,direct`),无需额外配置
#### 开发环境部署
1. **生成 Docker Compose 文件(可选,文件已存在)**
```bash
make docker-compose-dev
```
2. **启动服务**
2. **启动开发环境服务**
```bash
make docker-up-dev
```
3. **查看日志**
```bash
make docker-logs
```
4. **停止服务**
```bash
make docker-down-dev
```
#### 预发布环境部署
1. **启动预发布环境服务**
```bash
make docker-up-stage
```
2. **查看日志**
```bash
make docker-logs-stage
```
3. **停止服务**
```bash
make docker-down-stage
```
**注意:** 预发布环境使用不同的端口映射MySQL: 3307, Redis: 6380避免与开发环境冲突。
#### 生产环境部署
1. **设置环境变量(重要!)**
```bash
export MYSQL_ROOT_PASSWORD=your_secure_password
export REDIS_PASSWORD=your_redis_password
```
2. **启动生产环境服务**
```bash
make docker-up-prod
```
3. **查看日志**
```bash
make docker-logs-prod
```
4. **停止服务**
```bash
make docker-down-prod
```
**注意:**
- 生产环境使用不同的端口映射MySQL: 3308, Redis: 6381
- 生产环境配置了健康检查和自动重启策略
- 请务必在生产环境部署前修改配置文件中的敏感信息JWT密钥、数据库密码等
## 📋 可用命令
### 开发命令
@ -150,11 +298,18 @@ make docs-serve # 启动文档服务器
```bash
make docker-build # 构建 Docker 镜像
make docker-compose-dev # 生成开发环境 Docker Compose 文件
make docker-up-dev # 启动开发环境容器
make docker-up-stage # 启动预发布环境容器
make docker-up-prod # 启动生产环境容器
make docker-down # 停止容器
make docker-logs # 查看容器日志
make docker-down # 停止所有容器
make docker-down-dev # 停止开发环境容器
make docker-down-stage # 停止预发布环境容器
make docker-down-prod # 停止生产环境容器
make docker-logs # 查看开发环境容器日志
make docker-logs-stage # 查看预发布环境容器日志
make docker-logs-prod # 查看生产环境容器日志
make docker-ps # 查看所有容器状态
```
## 🔧 配置说明
@ -386,8 +541,15 @@ make build
3. **使用 Docker 部署**
```bash
make docker-compose-prod
# 设置环境变量
export MYSQL_ROOT_PASSWORD=your_secure_password
export REDIS_PASSWORD=your_redis_password
# 启动生产环境
make docker-up-prod
# 查看日志
make docker-logs-prod
```
### 环境变量
@ -451,4 +613,157 @@ A: 1. 在 `src/handler` 中添加处理函数
A: 在 `src/middleware` 目录下创建新的中间件文件,参考现有中间件的实现。
### Q: 如何部署到生产环境?
A: 使用 `make docker-compose-prod` 生成生产环境配置,然后使用 `make docker-up-prod` 部署。
A:
1. 设置环境变量:
```bash
export MYSQL_ROOT_PASSWORD=your_secure_password
export REDIS_PASSWORD=your_redis_password
```
2. 修改 `config/prod.yaml` 中的敏感配置JWT密钥等
3. 启动生产环境:
```bash
make docker-up-prod
```
4. 查看日志:
```bash
make docker-logs-prod
```
### Q: Docker Compose 支持哪些环境?
A: 项目支持三种环境的 Docker Compose 部署:
- **dev**: 开发环境,端口映射 MySQL:3306, Redis:6379
- **stage**: 预发布环境,端口映射 MySQL:3307, Redis:6380
- **prod**: 生产环境,端口映射 MySQL:3308, Redis:6381包含健康检查和自动重启
### Q: Docker 镜像拉取失败怎么办?
A: 如果在中国大陆遇到镜像拉取超时或失败,可以:
1. **配置 Docker 镜像加速器**(推荐):
```bash
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.nju.edu.cn"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
```
**重要:配置后必须重启 Docker 服务才能生效!**
验证配置:
```bash
docker info | grep -A 10 "Registry Mirrors"
```
如果看到镜像源列表,说明配置成功。
2. **Rootless Docker 配置**
- 如果使用 rootless Docker`docker version` 显示 `Context: rootless`),配置文件位置为 `~/.config/docker/daemon.json`
- 配置后重启:`systemctl --user restart docker`
- 验证:`docker info | grep -A 10 "Registry Mirrors"`
3. **使用官方镜像名称**:项目使用官方镜像名称(如 `mysql:8.0`、`redis:7-alpine`),通过配置的 Docker 镜像加速器自动加速拉取
4. **Go 模块下载失败**
- Dockerfile 中已配置使用国内 Go 代理(`GOPROXY=https://goproxy.cn,direct`
- 如果仍然失败,可以在 Dockerfile 中修改 GOPROXY 环境变量:
```dockerfile
ENV GOPROXY=https://goproxy.cn,https://goproxy.io,direct
```
- 常用 Go 代理:`https://goproxy.cn`、`https://goproxy.io`、`https://mirrors.aliyun.com/goproxy/`
5. **检查网络连接**:确保能够访问镜像仓库
- 测试镜像源:`curl -I https://docker.m.daocloud.io/v2/`
- 如果镜像加速器配置已生效但仍失败,可能是网络问题,可以稍后重试
6. **如果镜像加速器仍未生效**
- 检查配置文件格式是否正确JSON 格式)
- 标准 Docker检查 `/etc/docker/daemon.json`
- Rootless Docker检查 `~/.config/docker/daemon.json`
- 确认已重启 Docker 服务
- 检查 Docker 服务状态:`sudo systemctl status docker` 或 `systemctl --user status docker`
### Q: Docker 权限错误permission denied怎么办
A: 如果遇到 `Error response from daemon: cannot stop container: permission denied` 错误,可能的原因和解决方法:
1. **Docker 上下文不匹配**(常见原因):
如果系统同时安装了标准 Docker 和 rootless Docker容器可能由不同的上下文创建。
```bash
# 查看当前 Docker 上下文
docker context show
# 查看所有可用的上下文
docker context ls
# 如果容器是由标准 Docker 创建的,切换到 default 上下文
docker context use default
# 然后尝试停止容器
docker stop docker-mysql-1
# 如果需要切换回 rootless
docker context use rootless
```
**提示**:如果容器是通过 `sudo docker compose` 创建的,通常需要使用 `default` 上下文;如果通过普通用户创建的,可能使用 `rootless` 上下文。
2. **临时解决方案(使用 sudo**
```bash
# 停止并删除容器
sudo docker stop docker-mysql-1
sudo docker rm docker-mysql-1
# 或使用 docker compose
sudo docker compose -f docker/docker-compose.stage.yml down
```
3. **永久解决方案(推荐)**:将用户添加到 `docker`
```bash
# 将当前用户添加到 docker 组
sudo usermod -aG docker $USER
# 重新登录或执行以下命令使组权限生效
newgrp docker
# 验证是否成功
groups | grep docker
```
**注意**:添加到 docker 组后,需要:
- 重新登录系统,或
- 执行 `newgrp docker` 命令,或
- 重新打开终端
之后就可以不使用 `sudo` 直接操作 Docker 了。
4. **检查 Docker socket 权限**
```bash
ls -la /var/run/docker.sock
```
应该显示类似:`srw-rw---- 1 root docker`,表示 `docker` 组有读写权限。
5. **如果使用 rootless Docker**
- Rootless Docker 不需要 sudo但需要确保 Docker 服务正在运行
- 检查服务状态:`systemctl --user status docker`
- 启动服务:`systemctl --user start docker`
- 注意rootless Docker 和标准 Docker 创建的容器是隔离的,不能互相管理
- **如果遇到权限错误,可以尝试**
```bash
# 方法1重启 rootless Docker 服务(推荐)
systemctl --user restart docker
# 等待几秒后,再尝试停止容器
docker stop docker-mysql-1
# 方法2使用 docker kill 强制停止
docker kill docker-mysql-1
docker rm docker-mysql-1
# 方法3检查并修复 rootless Docker socket 权限
ls -la /run/user/$(id -u)/docker.sock
# 应该显示类似srw-rw---T 1 table ...
```

View File

@ -3,7 +3,7 @@ server:
mode: release
database:
host: localhost
host: mysql # Docker环境使用服务名本地环境使用localhost
port: 3306
username: root
password: sasasasa
@ -15,7 +15,7 @@ database:
maxOpenConns: 500
redis:
host: localhost
host: redis # Docker环境使用服务名本地环境使用localhost
port: 6379
password: ""
db: 2

View File

@ -3,7 +3,7 @@ server:
mode: release
database:
host: localhost
host: mysql # Docker环境使用服务名本地环境使用localhost
port: 3306
username: root
password: sasasasa
@ -15,7 +15,7 @@ database:
maxOpenConns: 200
redis:
host: localhost
host: redis # Docker环境使用服务名本地环境使用localhost
port: 6379
password: ""
db: 1

View File

@ -1,12 +1,10 @@
version: '3.8'
services:
yinli-api:
build:
context: ..
dockerfile: Dockerfile
ports:
- "8080:8080"
- "1234:1234"
environment:
- APP_ENV=dev
depends_on:
@ -29,6 +27,9 @@ services:
- ../sql:/docker-entrypoint-initdb.d:ro
networks:
- yinli-network
stop_grace_period: 60s
stop_signal: SIGTERM
init: true
redis:
image: redis:7-alpine

View File

@ -0,0 +1,71 @@
services:
yinli-api:
build:
context: ..
dockerfile: Dockerfile
ports:
- "1234:1234"
environment:
- APP_ENV=prod
depends_on:
- mysql
- redis
volumes:
- ../config:/app/config:ro
networks:
- yinli-network
restart: always
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:1234/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: yinli
ports:
- "3308:3306"
volumes:
- mysql_prod_data:/var/lib/mysql
- ../sql:/docker-entrypoint-initdb.d:ro
networks:
- yinli-network
restart: always
stop_grace_period: 60s
stop_signal: SIGTERM
init: true
command: --default-authentication-plugin=mysql_native_password
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6381:6379"
volumes:
- redis_prod_data:/data
networks:
- yinli-network
restart: always
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-}
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mysql_prod_data:
redis_prod_data:
networks:
yinli-network:
driver: bridge

View File

@ -0,0 +1,55 @@
services:
yinli-api:
build:
context: ..
dockerfile: Dockerfile
ports:
- "1234:1234"
environment:
- APP_ENV=stage
depends_on:
- mysql
- redis
volumes:
- ../config:/app/config:ro
networks:
- yinli-network
restart: unless-stopped
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-sasasasa}
MYSQL_DATABASE: yinli
ports:
- "3307:3306"
volumes:
- mysql_stage_data:/var/lib/mysql
- ../sql:/docker-entrypoint-initdb.d:ro
networks:
- yinli-network
restart: unless-stopped
stop_grace_period: 60s
stop_signal: SIGTERM
init: true
command: --default-authentication-plugin=mysql_native_password
redis:
image: redis:7-alpine
ports:
- "6380:6379"
volumes:
- redis_stage_data:/data
networks:
- yinli-network
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
mysql_stage_data:
redis_stage_data:
networks:
yinli-network:
driver: bridge