Install

Docker Compose

Run ImgYoung with the compose.yaml from the repository, and pair it with Caddy for automatic HTTPS.

The sample file

deploy/compose.yaml in the repository (release archives include a copy too):

deploy/compose.yaml
# ImgYoung 的 Docker Compose 示例。
# 用法:把本文件放进一个空目录,执行 docker compose up -d,浏览器打开 http://<主机>:8721/,
# 用 admin / imgyoung123 登录(首次登录强制改密)。
services:
  imgyoung:
    image: ghcr.io/x-haose/imgyoung:latest # 生产环境建议钉大小版本(如 1.0)或具体版本
    # 后台「从快照恢复」会让服务优雅退出,靠重启策略重新拉起后换入快照;正常退出也要拉起
    restart: unless-stopped
    # 优雅停机先停收新请求、等在途请求至多 6 秒,再停后台任务至多 2 秒;多出的是关库与退出的余量
    stop_grace_period: 15s
    ports:
      - "8721:8721"
    volumes:
      # 数据库、本地存储渠道与自动生成的 master.key 都在这里;丢了 master.key,渠道凭证与加密数据不可恢复
      - imgyoung-data:/data
    # environment:
    #   # 前面有反向代理时,不论代理在宿主机还是另一个容器,ImgYoung 看到的对端都是 Docker 网络里的地址,
    #   # 填该网络的网段(docker network inspect 查看);否则登录限速与 /metrics 放行会把所有请求都当成来自代理本身
    #   IMGYOUNG_TRUSTED_PROXIES: 172.16.0.0/12

volumes:
  imgyoung-data:

Put it in an empty directory and start it:

Terminal
mkdir imgyoung && cd imgyoung
curl -fsSLO https://raw.githubusercontent.com/x-haose/imgyoung/main/deploy/compose.yaml
docker compose up -d

Open http://<host>:8721/ and sign in with admin / imgyoung123; the first sign-in asks you to change the password right away.

Image tags, the contents of the data volume, environment variables and the restart policy are explained on Docker image and not repeated here. Before referencing host variables with ${VAR} under environment:, read the warning in the "Environment variables" section there: a variable the host does not set is substituted as an empty string.

stop_grace_period: 15s in the sample caps how long Compose waits for the process to exit on stop. On the stop signal ImgYoung stops accepting new requests and waits up to 6 seconds for in-flight ones, stops background work within 2 more seconds, then closes the database and exits; 15 seconds leaves headroom over those roughly 8.

Day-to-day operations

Run these in the directory that holds compose.yaml:

TaskCommand
Start, or apply changes to compose.yamldocker compose up -d
Show statusdocker compose ps
Follow the logsdocker compose logs -f imgyoung
Stop and remove the container (the volume is kept)docker compose down
Upgradedocker compose pull && docker compose up -d

Do not add -v

docker compose down -v also deletes the data volume, and with it the database, the images and master.key.

The volume's real name carries the project name as a prefix, and the project name defaults to the directory name: inside an imgyoung directory it is imgyoung_imgyoung-data. Check with docker volume ls.

To pin a version, change image: to a major.minor tag such as ghcr.io/x-haose/imgyoung:1.0, or to an exact version, then run docker compose up -d. Switching back to an older tag is not a downgrade: the older version refuses to start on a database migrated by a newer one. Before upgrading, consider clicking "Back up now" under "Settings → Backups & export"; see Upgrading for the rollback steps and more.

Serving HTTPS with Caddy

Caddy obtains and renews certificates automatically. Put the two files below in one directory, replace the domain with yours, point its DNS at this host, and open ports 80 and 443:

compose.yaml
Caddyfile
compose.yaml
services:
  imgyoung:
    image: ghcr.io/x-haose/imgyoung:latest
    restart: unless-stopped
    stop_grace_period: 15s
    # No published port: Caddy is the only entry point
    volumes:
      - imgyoung-data:/data
    environment:
      # Caddy runs in another container on the same Docker network; use that network's range
      IMGYOUNG_TRUSTED_PROXIES: 172.16.0.0/12

  caddy:
    image: caddy:2
    restart: unless-stopped
    depends_on:
      - imgyoung
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config

volumes:
  imgyoung-data:
  caddy-data:
  caddy-config:
Caddyfile
img.example.com {
	# Metrics are for internal scraping only; never forward them from the public entry point
	respond /metrics 404

	reverse_proxy imgyoung:8721
}

The only configuration difference from deploy/Caddyfile in the repository is the upstream: Caddy runs in a container, so it reaches ImgYoung by service name, imgyoung:8721, instead of 127.0.0.1:8721.

Notes:

  • Why IMGYOUNG_TRUSTED_PROXIES is needed. By default ImgYoung trusts forwarding headers only from loopback, but Caddy connects from a private address on the Docker network. Without it, login rate limiting treats every visitor as the same client, returned image links use http:// instead of https://, and the session cookie is not marked Secure.
  • Check the subnet. The network Compose creates for the project usually falls inside 172.16.0.0/12, but once Docker's default pools there are used up it allocates from 192.168.0.0/16 as well. Run docker network inspect imgyoung_default (when the project is named after the directory) and look at Subnet; if it is outside 172.16.0.0/12, use the actual subnet.
  • Certificates and Caddy's data. Certificates live in the caddy-data volume; deleting it makes Caddy request new ones.
  • Upload size. Caddy does not limit request body size by default, so the only limit is "Max image size" in the console (50 MB by default).
  • Link addresses. With the proxy trusted and no base_url configured, links are built from the host and scheme Caddy forwards, i.e. https://img.example.com/i/.... You only need base_url when the public domain differs from the one Caddy receives (for example with a CDN in front); see Configuration.
  • Metrics. The public entry point blocks /metrics; a Prometheus on the same network can scrape imgyoung:8721/metrics directly, since private addresses are allowed by default. See Monitoring.

For Nginx and other proxies, see Reverse proxy.

On this page