Skip to content

Commit f83ab46

Browse files
committed
feat: add Docker Compose and Docker Stack configurations for mx-core and Redis services
- Introduced `docker-compose.server.yml` for local development with mx-core and Redis services. - Added `docker-stack.server.yml` for deploying mx-core and Redis in a Docker Swarm environment. - Configured health checks, environment variables, and volume bindings for both services. - Updated GitHub Actions workflow to support deployment of the new configurations. Signed-off-by: Innei <tukon479@gmail.com>
1 parent 481f483 commit f83ab46

3 files changed

Lines changed: 247 additions & 22 deletions

File tree

.github/workflows/release.yml

Lines changed: 91 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -184,42 +184,111 @@ jobs:
184184
run: |
185185
docker buildx imagetools inspect ${{ env.IMAGE }}:${{ steps.meta.outputs.version }}
186186
deploy:
187-
name: Deploy To Remote Server
187+
name: Deploy Docker Image To Remote Server
188188
runs-on: ubuntu-latest
189-
needs: [build]
189+
needs: [merge]
190190
steps:
191-
- uses: robinraju/release-downloader@v1.12
192-
name: Download release
191+
- name: Checkout (for docker-compose.server.yml)
192+
uses: actions/checkout@v6
193+
194+
- name: Generate env file for server (mx-core.env)
195+
shell: bash
196+
run: |
197+
set -euo pipefail
198+
cat > mx-core.env <<'EOF'
199+
TZ=${TZ:-Asia/Shanghai}
200+
MX_PORT=${MX_PORT:-2333}
201+
ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-localhost:*}
202+
DB_CONNECTION_STRING=${DB_CONNECTION_STRING:-mongodb://host.docker.internal:27017/mx-space}
203+
ENCRYPT_ENABLE=${ENCRYPT_ENABLE:-true}
204+
ENCRYPT_KEY=${ENCRYPT_KEY:-}
205+
JWT_SECRET=${JWT_SECRET:-}
206+
JWT_EXPIRE=${JWT_EXPIRE:-}
207+
DISABLE_CACHE=${DISABLE_CACHE:-false}
208+
DEBUG=${DEBUG:-false}
209+
DEBUG_MEMORY_DUMP=${DEBUG_MEMORY_DUMP:-false}
210+
EOF
211+
env:
212+
# Values come from CI-provided env/secrets. Server doesn't need a pre-created .env.
213+
TZ: ${{ secrets.TZ }}
214+
MX_PORT: ${{ secrets.MX_PORT }}
215+
ALLOWED_ORIGINS: ${{ secrets.ALLOWED_ORIGINS }}
216+
DB_CONNECTION_STRING: ${{ secrets.DB_CONNECTION_STRING }}
217+
ENCRYPT_ENABLE: ${{ secrets.ENCRYPT_ENABLE }}
218+
ENCRYPT_KEY: ${{ secrets.MX_ENCRYPT_KEY }}
219+
JWT_SECRET: ${{ secrets.JWTSECRET }}
220+
JWT_EXPIRE: ${{ secrets.JWT_EXPIRE }}
221+
DISABLE_CACHE: ${{ secrets.DISABLE_CACHE }}
222+
DEBUG: ${{ secrets.DEBUG }}
223+
DEBUG_MEMORY_DUMP: ${{ secrets.DEBUG_MEMORY_DUMP }}
224+
225+
- name: Ensure deploy dir exists
226+
uses: appleboy/ssh-action@v1.2.0
193227
with:
194-
tag: ${{ github.ref_name }}
195-
fileName: release-linux.zip
196-
- name: copy file via ssh password
228+
command_timeout: 2m
229+
host: ${{ secrets.HOST }}
230+
username: ${{ secrets.USER }}
231+
password: ${{ secrets.PASSWORD }}
232+
key: ${{ secrets.KEY }}
233+
script: |
234+
set -euo pipefail
235+
mkdir -p "$HOME/mx-core-deploy"
236+
237+
- name: Upload docker-compose.server.yml to server
197238
uses: appleboy/scp-action@v0.1.7
198239
with:
199240
host: ${{ secrets.HOST }}
200241
username: ${{ secrets.USER }}
201242
password: ${{ secrets.PASSWORD }}
202-
# port: ${{ secrets.PORT }}
203243
key: ${{ secrets.KEY }}
204-
source: release-linux.zip
205-
target: /tmp/mx-core
244+
source: docker-compose.server.yml,docker-stack.server.yml,mx-core.env
245+
target: mx-core-deploy
206246

207-
- name: Exec deploy script with SSH
208-
uses: appleboy/ssh-action@master
247+
- name: Deploy with SSH (docker swarm)
248+
uses: appleboy/ssh-action@v1.2.0
209249
env:
210-
JWTSECRET: ${{ secrets.JWTSECRET }}
211-
MX_ENCRYPT_KEY: ${{ secrets.MX_ENCRYPT_KEY }}
250+
IMAGE_REPO: ${{ env.IMAGE }}
251+
REF_NAME: ${{ github.ref_name }}
212252
with:
213-
command_timeout: 5m
253+
command_timeout: 10m
214254
host: ${{ secrets.HOST }}
215255
username: ${{ secrets.USER }}
216256
password: ${{ secrets.PASSWORD }}
217257
key: ${{ secrets.KEY }}
218-
envs: JWTSECRET,MX_ENCRYPT_KEY
258+
envs: IMAGE_REPO,REF_NAME
219259
script: |
220-
whoami
221-
cd
222-
source ~/.zshrc
223-
cd mx
224-
ls -a
225-
node server-deploy.js --jwtSecret=$JWTSECRET --encrypt_key=$MX_ENCRYPT_KEY --encrypt_enable --scp_path=/tmp/mx-core/release-linux.zip || { echo "Deploy failed"; exit 1; }
260+
set -euo pipefail
261+
cd "$HOME/mx-core-deploy"
262+
263+
IMAGE_TAG="${REF_NAME#v}"
264+
FULL_IMAGE="${IMAGE_REPO}:${IMAGE_TAG}"
265+
266+
echo "[deploy] pulling ${FULL_IMAGE}"
267+
docker pull "${FULL_IMAGE}"
268+
269+
# Ensure swarm mode (single-node swarm is OK)
270+
if [ "$(docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null || echo inactive)" != "active" ]; then
271+
echo "[deploy] swarm not active, init swarm"
272+
docker swarm init
273+
fi
274+
275+
# Load env for ${...} substitutions in stack file
276+
if [ -f "./mx-core.env" ]; then
277+
chmod 600 ./mx-core.env || true
278+
set -a
279+
. ./mx-core.env
280+
set +a
281+
else
282+
echo "[deploy] missing mx-core.env (upload failed?)"
283+
exit 1
284+
fi
285+
286+
echo "[deploy] starting via swarm stack"
287+
export MX_CORE_IMAGE="${FULL_IMAGE}"
288+
docker stack deploy -c docker-stack.server.yml mx-core --with-registry-auth
289+
290+
echo "[deploy] status"
291+
docker stack services mx-core
292+
293+
echo "[deploy] cleanup"
294+
docker image prune -f || true

docker-compose.server.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
services:
2+
mx-core:
3+
# CI build this image, then ship it to your SERVER.
4+
# e.g. ghcr.io/<org>/<repo>:<tag>
5+
image: ${MX_CORE_IMAGE:-mx-core:latest}
6+
container_name: mx-core
7+
restart: unless-stopped
8+
9+
ports:
10+
- "${MX_PORT:-2333}:2333"
11+
12+
# For Linux hosts: allow reaching host Mongo via host.docker.internal
13+
extra_hosts:
14+
- "host.docker.internal:host-gateway"
15+
16+
environment:
17+
TZ: ${TZ:-Asia/Shanghai}
18+
PORT: "2333"
19+
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-localhost:*}
20+
21+
# MongoDB (host machine)
22+
DB_CONNECTION_STRING: ${DB_CONNECTION_STRING:-mongodb://host.docker.internal:27017/mx-space}
23+
24+
# Redis (container in this compose)
25+
REDIS_HOST: redis
26+
REDIS_PORT: "6379"
27+
# REDIS_PASSWORD: ${REDIS_PASSWORD:-}
28+
29+
# Security (optional)
30+
# ENCRYPT_KEY must be length 64 if ENCRYPT_ENABLE=true
31+
ENCRYPT_ENABLE: ${ENCRYPT_ENABLE:-true}
32+
ENCRYPT_KEY: ${ENCRYPT_KEY:-}
33+
JWT_SECRET: ${JWT_SECRET:-}
34+
JWT_EXPIRE: ${JWT_EXPIRE:-}
35+
36+
# Cache
37+
DISABLE_CACHE: ${DISABLE_CACHE:-false}
38+
39+
# Debug (optional)
40+
DEBUG: ${DEBUG:-false}
41+
DEBUG_MEMORY_DUMP: ${DEBUG_MEMORY_DUMP:-false}
42+
43+
volumes:
44+
# production data dir: ~/.mx-space
45+
- ./data/mx-space:/root/.mx-space
46+
47+
depends_on:
48+
- redis
49+
50+
healthcheck:
51+
test: [CMD, curl, -f, "http://127.0.0.1:2333/api/v2/ping"]
52+
interval: 1m30s
53+
timeout: 30s
54+
retries: 5
55+
start_period: 30s
56+
57+
redis:
58+
image: redis:7-alpine
59+
container_name: mx-redis
60+
restart: unless-stopped
61+
command: ["redis-server", "--appendonly", "yes"]
62+
volumes:
63+
- ./data/redis:/data
64+
healthcheck:
65+
test: [CMD-SHELL, "redis-cli ping | grep PONG"]
66+
start_period: 20s
67+
interval: 30s
68+
retries: 5
69+
timeout: 3s
70+

docker-stack.server.yml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
services:
2+
mx-core:
3+
image: ${MX_CORE_IMAGE:-mx-core:latest}
4+
ports:
5+
- target: 2333
6+
published: ${MX_PORT:-2333}
7+
protocol: tcp
8+
mode: ingress
9+
10+
extra_hosts:
11+
- "host.docker.internal:host-gateway"
12+
13+
environment:
14+
TZ: ${TZ:-Asia/Shanghai}
15+
PORT: "2333"
16+
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-localhost:*}
17+
18+
# MongoDB (host machine)
19+
DB_CONNECTION_STRING: ${DB_CONNECTION_STRING:-mongodb://host.docker.internal:27017/mx-space}
20+
21+
# Redis (service in this stack)
22+
REDIS_HOST: redis
23+
REDIS_PORT: "6379"
24+
25+
# Security (optional)
26+
ENCRYPT_ENABLE: ${ENCRYPT_ENABLE:-true}
27+
ENCRYPT_KEY: ${ENCRYPT_KEY:-}
28+
JWT_SECRET: ${JWT_SECRET:-}
29+
JWT_EXPIRE: ${JWT_EXPIRE:-}
30+
31+
DISABLE_CACHE: ${DISABLE_CACHE:-false}
32+
DEBUG: ${DEBUG:-false}
33+
DEBUG_MEMORY_DUMP: ${DEBUG_MEMORY_DUMP:-false}
34+
35+
volumes:
36+
- type: bind
37+
source: ./data/mx-space
38+
target: /root/.mx-space
39+
40+
depends_on:
41+
- redis
42+
43+
healthcheck:
44+
test: ["CMD", "curl", "-f", "http://127.0.0.1:2333/api/v2/ping"]
45+
interval: 30s
46+
timeout: 5s
47+
retries: 10
48+
start_period: 30s
49+
50+
deploy:
51+
replicas: 2
52+
restart_policy:
53+
condition: any
54+
update_config:
55+
parallelism: 1
56+
order: start-first
57+
delay: 10s
58+
failure_action: rollback
59+
monitor: 30s
60+
rollback_config:
61+
parallelism: 1
62+
order: stop-first
63+
monitor: 30s
64+
65+
redis:
66+
image: redis:7-alpine
67+
command: ["redis-server", "--appendonly", "yes"]
68+
volumes:
69+
- type: bind
70+
source: ./data/redis
71+
target: /data
72+
healthcheck:
73+
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
74+
interval: 30s
75+
timeout: 3s
76+
retries: 5
77+
start_period: 20s
78+
deploy:
79+
replicas: 1
80+
restart_policy:
81+
condition: any
82+
83+
networks:
84+
default:
85+
name: mx-core
86+
driver: overlay

0 commit comments

Comments
 (0)