Forgejo with Docker: ports, storage and recovery
A reliable Forgejo setup needs a supported release, persistent data, the correct external URL and a tested recovery procedure. Start with a local-only instance before exposing a new service. This guide uses the standard Docker image; rootless images have different storage paths and SSH ports and must follow their own documentation.
Choose and verify the installation method
Read Forgejo's Docker installation guide and release information. The example below pins the v17.0.0 image documented at this review. Check the current supported release and upgrade notes before a real deployment. A tag identifies a version; use a verified image digest when your deployment requires an immutable reference.
Do not assume a package exists in every Linux distribution, a historical minimum Git version remains supported or every Gitea version can be upgraded by substituting a binary. Follow the documented path for the actual source and destination versions.
A local-only Compose example
This single-service example uses SQLite for a small local evaluation. It binds the web and SSH ports to loopback and keeps the standard image's data in a named volume. It is not a complete public production configuration.
services:
forgejo:
image: codeberg.org/forgejo/forgejo:17.0.0
environment:
USER_UID: "1000"
USER_GID: "1000"
FORGEJO__database__DB_TYPE: sqlite3
FORGEJO__server__ROOT_URL: http://localhost:3000/
FORGEJO__server__SSH_DOMAIN: localhost
FORGEJO__server__SSH_PORT: "2222"
ports:
- "127.0.0.1:3000:3000"
- "127.0.0.1:2222:22"
volumes:
- forgejo-data:/data
restart: unless-stopped
volumes:
forgejo-data:
Save it as compose.yaml, inspect the resolved configuration, then start it when ready:
docker compose config
docker compose up -d
docker compose logs --tail=50 forgejo
Open http://localhost:3000/ on the same computer and complete the authorized initial configuration. An admin account is not created by this example. Keep data you care about out of the evaluation until you have verified the setup and recovery procedure. Do not use docker compose down -v as an ordinary stop command: it can remove the named volume.
Distinguish an advertised port from a listening port
In the standard image, the mapping above sends host port 2222 to container port 22. SSH_PORT advertises the external port in clone URLs; it is not a reason to copy a rootless image's internal port. The rootless example in Forgejo's documentation instead uses internal port 2222 and different data paths. Mixing those two examples was an error in the earlier answer.
Before allowing public access
- Choose the intended public hostname and configure
ROOT_URLto match it. - Follow the reverse-proxy guide. If a proxy terminates HTTPS and forwards HTTP internally, setting the application's listener to HTTPS is not automatically correct.
- Review registration, administrator access, trusted proxy settings and network exposure for the intended users.
- Keep configuration and database credentials out of public repositories and screenshots.
- Evaluate the documented database choices for the workload instead of assuming a local SQLite example is a tested production design.
Prove recovery before relying on the server
Follow Forgejo's backup and restoration guidance for the database, repositories, configuration and other stored assets. Stop or coordinate writes as required for a consistent backup. Restore into an isolated location and check repository access and important application data. A downloaded image or a Git copy of a repository is not a backup of the entire service.
For upgrades, read the upgrade guide, retain the required recovery material and verify compatibility before changing the image. Forgejo Actions runners execute jobs and need a separate security design; this setup does not install or register a runner. The example is a documented configuration, not a claim that a public Forgejo service was deployed or load-tested here.