Skip to main content
Version: 4.x

Install with Docker

Docker is the recommended way to run Spug. Both official images bundle Nginx, Redis and every background service, and the database runs in a separate MariaDB container:

  • Option A: openspug/spug (recommended). The back end and the web UI are built into the image, so the container needs no internet access to start, and upgrading is docker compose pull.
  • Option B: openspug/spug-service. The image only contains the runtime; on first start the container downloads the code from gitee.com and cdn.spug.cc. Use it if those mirrors are faster for you than Docker Hub / GitHub, for example in mainland China.

Both images are published for amd64 and arm64 (Kunpeng, Phytium, Graviton, Raspberry Pi 4/5, Apple Silicon, ...) and Docker picks the right one automatically. 32-bit ARM (armv7) is not supported.

Option A: all-in-one image (recommended)​

Requirements: Docker 20.10.10 or later with the docker compose plugin (how to install). Older engines block a system call (clone3) that the C library in the image needs; the container detects that and exits with a message.

mkdir -p /opt/spug && cd /opt/spug
curl -fsSLO https://raw.githubusercontent.com/openspug/spug/4.0/docker-compose.yml
docker compose up -d
docker compose logs spug | grep password

On the first start the container creates the tables and an admin account with a random password, which the last command prints. Open http://<server-ip>/, log in, and change the password under Profile in the avatar menu (top right).

The settings in docker-compose.yml:

SettingDescription
ports: "80:80"Change the left side if port 80 is taken, e.g. "8080:80"
TZTime zone of scheduled tasks and of the timestamps shown in the UI, UTC by default, e.g. America/New_York, Europe/Berlin
SPUG_DB_PASSWORDDatabase password, spug.cc by default. The database is only reachable from the Spug container; to use your own, put SPUG_DB_PASSWORD=... into a .env file next to docker-compose.yml before the first start, because the database volume keeps the password it was created with
SPUG_ADMIN_PASSWORDOptional password for the first admin account instead of a random one; only used while the database has no users
MYSQL_*Database connection; point them to your own MySQL 8 / MariaDB 10.4+ to use it instead of the db service
cap_add / devices / security_optDistributing files from a host and the pipeline "data transfer" node mount the source host with sshfs (FUSE). These three settings allow exactly that instead of privileged: true; remove them if you don't use those two features
volume spug-data/data in the container: configuration (spug/spug_api/spug/overrides.py), logs, generated database migrations, uploaded files, and the git checkouts / build artifacts of deployments
volume spug-dbDatabase files

Upgrade with docker compose pull && docker compose up -d. On every start the container copies the code of the image into the spug-data volume and applies database changes; configuration and data stay in place. Pin an exact version (e.g. openspug/spug:4.1.0) in docker-compose.yml if you prefer to upgrade explicitly. The image is also published as ghcr.io/openspug/spug with the same tags.

Just looking? docker run -d --name spug -p 8080:80 openspug/spug:4.1 starts a single container that uses SQLite instead of MySQL (docker logs spug | grep password for the login). That is fine for a test drive; use the compose file above for real use.

Legacy all-in-one image (3.x)

Up to 3.3.2, openspug/spug was an image with MariaDB inside the container (docker run ... -v /mydata:/data openspug/spug). A 4.x container refuses to start on such a volume and leaves it untouched. Keep that installation on openspug/spug:3.3.2, or back up its database first (docker exec spug mysqldump -uspug -pspug.dev spug > spug.sql) and ask in GitHub issues for help moving it to 4.x.

Option B: spug-service image​

On Docker Hub both tags of openspug/spug-service, 4.0 (the 4.0 release this section covers, current code version v4.0.1) and latest (3.x, not 4.0), are multi-architecture. ARM64 hosts must pull from Docker Hub; the Alibaba Cloud registry currently only has x86 images of 3.x.

Requirements: Docker 20.10 or later (with the docker compose plugin).

The steps below use Ubuntu 22.04 / CentOS 7; only the Docker installation command differs on other Linux distributions.

1. Install Docker​

Note

Skip this step if Docker is already installed. For other systems see the Docker documentation.

# CentOS / RHEL
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-compose-plugin
systemctl enable docker
systemctl start docker
# Ubuntu / Debian
curl -fsSL https://get.docker.com | bash
systemctl enable docker
systemctl start docker

2. Create docker-compose.yml​

mkdir -p /data/spug && cd /data/spug
vi docker-compose.yml
version: "3.3"
services:
db:
image: mariadb:10.8
container_name: spug-db
restart: always
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- /data/spug/mysql:/var/lib/mysql
environment:
- MYSQL_DATABASE=spug
- MYSQL_USER=spug
- MYSQL_PASSWORD=spug.cc
- MYSQL_ROOT_PASSWORD=spug.cc
spug:
image: openspug/spug-service:4.0
container_name: spug
privileged: true
restart: always
volumes:
- /data/spug/service:/data/spug
- /data/spug/repos:/data/repos
ports:
# if port 80 is taken, map another one, e.g. - "8000:80"
- "80:80"
environment:
- SPUG_DOCKER_VERSION=v4.0.1
- MYSQL_DATABASE=spug
- MYSQL_USER=spug
- MYSQL_PASSWORD=spug.cc
- MYSQL_HOST=db
- MYSQL_PORT=3306
depends_on:
- db

What the settings mean:

Path / settingDescription
/data/spug/mysqlDatabase files, must be persisted
/data/spug/serviceSpug program directory (/data/spug inside the container); on first start the version selected by SPUG_DOCKER_VERSION is cloned from gitee, the front-end bundle is downloaded and spug_api/spug/overrides.py is generated
/data/spug/reposGit checkouts and build artifacts of standard deployments
SPUG_DOCKER_VERSIONCode version (git tag) fetched on first start; it must match the image version, use v4.0.1 with the 4.0 image. There is no default: without it the container exits while cloning and keeps restarting
MYSQL_*Database connection, must match the db service; can point to your own MySQL instead, see external MySQL
privileged: trueRequired by file distribution, which mounts remote directories with sshfs
Registry mirror

The Alibaba Cloud registry registry.cn-hangzhou.aliyuncs.com/openspug/spug-service currently only provides x86 images of 3.x, with neither a 4.0 tag nor ARM64 builds, so do not replace the image above with the Alibaba Cloud address. If pulling from Docker Hub fails because of network restrictions, configure a Docker Hub registry mirror for the Docker daemon (registry-mirrors in /etc/docker/daemon.json, then restart Docker); the image names in docker-compose.yml stay unchanged.

3. Start the containers​

docker compose up -d
Note

With the legacy standalone docker-compose binary run docker-compose up -d instead.

The first start needs internet access

Unlike the 3.x image, which ships with the code built in, the 4.0 image does not contain the code: on first start the container clones the version selected by SPUG_DOCKER_VERSION from gitee.com and downloads the matching front-end bundle from cdn.spug.cc. Make sure the server can reach both hosts; the first start cannot complete on an isolated / offline network. Fetching the code and initializing the database usually takes 10 to 30 seconds (follow the container log with docker logs -f spug); run step 4 once it is done.

4. Initialize​

The command below creates the database tables and an administrator account with user name admin and password spug.cc; replace them with your own values.

docker exec spug init_spug admin spug.cc
Tip

On the very first start wait until the code has been fetched and the database is ready (usually 10 to 30 seconds) before running the command. If it fails with can't open file '/data/spug/spug_api/manage.py' (the code is still being fetched) or Can't connect to MySQL server on 'db:3306' (the database is still initializing), wait a few seconds and run it again.

5. Open Spug​

Open http://<server-ip>:80 in the browser and log in with the account created in step 4. The globe icon in the header switches between English and Chinese.

6. Upgrading​

The running version is shown under System / Settings / About, the latest version is listed in the change log, and the upgrade procedure is described in Upgrade.

Day-to-day commands​

# follow the container log
docker logs -f spug

# open a shell in the container
docker exec -it spug bash

# processes of every service (gunicorn = api, daphne = ws, runworker / runmonitor / runscheduler, nginx, redis)
# openspug/spug: `docker exec spug supervisorctl status` lists the services
# openspug/spug-service 4.0: supervisord has no RPC interface, so supervisorctl does not work; restart the container instead
docker exec spug ps -ef

# restart the container
docker restart spug

Directory layout inside the container:

PathDescription
/data/spug/spug_apiBack-end code, local overrides in spug/overrides.py
/data/spug/spug_api/logsLog files of the background services
/data/spug/envEnvironment file of the 3.x image; the 4.0 image no longer reads it. Put container-wide variables into the environment of docker-compose.yml, see command not found
/etc/nginx/nginx.confNginx configuration
/etc/supervisord.confBackground service definitions; supervisord starts nginx, redis and the Spug services directly from this file

Security recommendations​

  • Do not expose Spug directly to the internet. If public access is unavoidable, restrict source IPs with a firewall and enable login MFA under System / Settings / Security Settings.
  • When you put another reverse proxy (Nginx etc.) in front of the container's port 80, forward the X-Forwarded-For header and enable WebSocket forwarding, see WebSocket.
  • Change the default database password in docker-compose.yml.