Blame
| 8ded1f | Freedom | 2026-01-29 18:06:57 | 1 | # Wechat Official Editor |
| c61bf2 | Freedom | 2026-01-29 17:59:51 | 2 | |
| 3 | ## Goal |
|||
| 4 | ||||
| 5 | * Run the WeChat Official Account editor as a Docker container. |
|||
| 6 | * Persist data with volumes. |
|||
| 7 | * Expose it at `woeditor.manxialiu.org` behind Nginx + TLS. |
|||
| 8 | ||||
| 9 | ## Prerequisites |
|||
| 10 | ||||
| 11 | * A working Docker + Docker Compose setup. |
|||
| 12 | * An Nginx reverse proxy container (or host Nginx). |
|||
| 13 | * A Certbot flow that can issue/renew certs for `woeditor.manxialiu.org`. |
|||
| 14 | ||||
| 15 | I’m assuming you already use the shared `nginx` + `certbot` pattern from the other services. |
|||
| 16 | ||||
| 17 | ## Docker Compose service |
|||
| 18 | ||||
| 19 | Add a service to your existing `compose.yml`. |
|||
| 20 | ||||
| 21 | Replace: |
|||
| 22 | ||||
| 23 | * `REPLACE_WITH_IMAGE` with the actual image name. |
|||
| 24 | * `INTERNAL_PORT` with the port the app listens on inside the container. |
|||
| 25 | ||||
| 26 | ```yaml |
|||
| 27 | woeditor: |
|||
| 28 | image: REPLACE_WITH_IMAGE |
|||
| 29 | container_name: woeditor |
|||
| 30 | restart: unless-stopped |
|||
| 31 | environment: |
|||
| 32 | TZ: "UTC" |
|||
| 33 | # Add app-specific env vars here. |
|||
| 34 | volumes: |
|||
| 35 | - ./woeditor/data:/data |
|||
| 36 | # Add other persistent paths required by the app. |
|||
| 37 | expose: |
|||
| 38 | - "INTERNAL_PORT" |
|||
| 39 | ``` |
|||
| 40 | ||||
| 41 | ||||
| 42 | Don’t publish the app port directly (`ports:`) if Nginx is the only entry point. Use `expose:` so it stays internal to the Docker network. |
|||
| 43 | ||||
| 44 | ## Nginx reverse proxy config |
|||
| 45 | ||||
| 46 | Add a server block for the subdomain. |
|||
| 47 | ||||
| 48 | ```yaml |
|||
| 49 | version: "3.9" |
|||
| 50 | ||||
| 51 | services: |
|||
| 52 | certbot: |
|||
| 53 | image: certbot/certbot:latest |
|||
| 54 | container_name: certbot |
|||
| 55 | volumes: |
|||
| 56 | - ./certbot/www:/var/www/certbot |
|||
| 57 | - ./certbot/conf:/etc/letsencrypt |
|||
| 58 | ||||
| 59 | nginx: |
|||
| 60 | image: nginx:alpine |
|||
| 61 | container_name: nginx |
|||
| 62 | restart: unless-stopped |
|||
| 63 | depends_on: |
|||
| 64 | - freshrss |
|||
| 65 | - wallabag |
|||
| 66 | ports: |
|||
| 67 | - "80:80" |
|||
| 68 | - "443:443" |
|||
| 69 | volumes: |
|||
| 70 | - ./nginx/conf.d:/etc/nginx/conf.d:ro |
|||
| 71 | - ./certbot/www:/var/www/certbot:ro |
|||
| 72 | - ./certbot/conf:/etc/letsencrypt:ro |
|||
| 73 | ||||
| 74 | woeditor: |
|||
| 75 | image: wechatofficial:latest |
|||
| 76 | container_name: woeditor |
|||
| 77 | ports: |
|||
| 78 | - "5173:5173" |
|||
| 79 | environment: |
|||
| 80 | - NODE_ENV=development |
|||
| 81 | # Hot reload: mount your code into the container |
|||
| 82 | volumes: |
|||
| 83 | - ./WechatOfficialEditor:/app |
|||
| 84 | # Keep container's node_modules (avoids overwriting by the bind mount) |
|||
| 85 | - /app/node_modules |
|||
| 86 | command: pnpm web dev --host 0.0.0.0 --port 5173 |
|||
| 87 | ``` |
|||
| 88 | ||||
| 89 | ## Certificates |
|||
| 90 | ||||
| 91 | If you’re using a single SAN cert, add `woeditor.manxialiu.org` to the cert request and re-run Certbot. |
|||
| 92 | ||||
| 93 | ```bash |
|||
| 94 | docker compose run --rm certbot certonly \ |
|||
| 95 | --webroot -w /var/www/certbot \ |
|||
| 96 | -d woeditor.manxialiu.org \ |
|||
| 97 | --email you@example.com \ |
|||
| 98 | --agree-tos \ |
|||
| 99 | --no-eff-email |
|||
| 100 | ``` |
|||
| 101 | ||||
| 102 | ## Bring it up |
|||
| 103 | ||||
| 104 | ```bash |
|||
| 105 | docker compose up -d woeditor nginx |
|||
| 106 | ``` |
|||
| 107 | ||||
| 108 | Quick checks: |
|||
| 109 | ||||
| 110 | * `docker compose ps` |
|||
| 111 | * `docker logs -f woeditor` |
|||
| 112 | * `curl -I https://woeditor.manxialiu.org` |
|||
| 113 | ||||
| 114 | ## What I need from you to make this exact |
|||
| 115 | ||||
| 116 | Send these and I’ll tighten the section with concrete values: |
|||
| 117 | ||||
| 118 | * Docker image name (or repo URL) |
|||
| 119 | * Internal port the app listens on |
|||
| 120 | * Any required env vars |
|||
| 121 | * Any DB requirement (Postgres/MariaDB/SQLite) |
|||
| 122 | * Which paths must be persisted |
