This note records a DS2API deployment with Docker Compose.
Example values:
- public domain:
ds2api.example.com - public HTTPS port:
8446 - app port inside container:
5001 - host port bound to localhost:
6011 - admin key:
example_ds2api_admin_key_change_me - API key:
sk-example-ds2api-key-please-change
All keys above are fake.
Clone
git clone https://github.com/CJackHwang/ds2api.gitcd ds2apicp .env.example .envcp config.example.json config.jsonEnvironment
Edit .env:
PORT=5001DS2API_HOST_PORT=6011LOG_LEVEL=INFODS2API_ADMIN_KEY=example_ds2api_admin_key_change_meDS2API_CONFIG_PATH=/app/config.jsonThe app listens on PORT inside the container. DS2API_HOST_PORT is the host-side port used by Docker Compose.
Prefer binding the host port to localhost:
ports: - "127.0.0.1:6011:5001"config.json
Minimal example:
{ "keys": [ "sk-example-ds2api-key-please-change" ], "api_keys": [ { "key": "sk-example-ds2api-key-please-change", "name": "main", "remark": "for OpenAI-compatible clients" } ], "accounts": [ { "name": "main-account", "email": "deepseek-user@example.com", "password": "example-password-please-change" } ], "model_aliases": { "gpt-4o": "deepseek-v4-flash", "gpt-5": "deepseek-v4-pro" }, "runtime": { "account_max_inflight": 2, "account_max_queue": 5, "token_refresh_interval_hours": 6 }}DeepSeek account passwords and refresh tokens are credentials. Treat config.json as a secret file.
Start
docker compose up -ddocker compose logs -fCheck logs:
docker logs --tail 200 -f ds2apiCaddy Reverse Proxy
ds2api.example.com:8446 { reverse_proxy 127.0.0.1:6011}Reload:
sudo caddy validate --config /etc/caddy/Caddyfilesudo systemctl reload caddyOpen the firewall port if needed:
sudo nft add rule inet filter input tcp dport 8446 acceptTest
curl https://ds2api.example.com:8446/v1/models \ -H "Authorization: Bearer sk-example-ds2api-key-please-change"Chat completion:
curl https://ds2api.example.com:8446/v1/chat/completions \ -H "Authorization: Bearer sk-example-ds2api-key-please-change" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-v4-flash", "messages": [{"role": "user", "content": "ping"}], "stream": false }'Notes
- Change
DS2API_ADMIN_KEY; do not leave a default admin password. - Keep
config.jsonprivate because it stores upstream account credentials. - Bind the service to
127.0.0.1and publish it through Caddy. - Do not paste real
sk-...keys into public docs.