services: 3xui: build: context: . dockerfile: ./Dockerfile container_name: 3xui_app # hostname: yourhostname <- optional # Optional hard memory cap. When set, the panel auto-derives its Go soft # limit (GOMEMLIMIT, ~90%) from this so it GCs before the OOM killer fires. # mem_limit: 512m # The bundled Fail2ban (XUI_ENABLE_FAIL2BAN below) enforces the IP limit # with iptables, which needs NET_ADMIN. Without these caps a ban is logged # and shown in fail2ban status but never actually applied. NET_RAW covers # ip6tables. If you disable Fail2ban, you can drop cap_add. cap_add: - NET_ADMIN - NET_RAW volumes: - $PWD/db/:/etc/x-ui/ - $PWD/cert/:/root/cert/ environment: XRAY_VMESS_AEAD_FORCED: "false" XUI_ENABLE_FAIL2BAN: "true" # Go memory soft limit. If neither is set, the panel auto-detects the # cgroup/host limit and targets ~90%. Pin it explicitly with one of: # XUI_MEMORY_LIMIT: "400" # in MiB # GOMEMLIMIT: "400MiB" # Go syntax, takes precedence # XUI_PPROF: "true" # expose pprof on 127.0.0.1:6060 for profiling # XUI_INIT_WEB_BASE_PATH: "/" # XUI_PORT: "8080" # To use PostgreSQL instead of the default SQLite, run: # docker compose --profile postgres up -d # and uncomment the two lines below. # XUI_DB_TYPE: "postgres" # XUI_DB_DSN: "postgres://xui:xui@postgres:5432/xui?sslmode=disable" tty: true ports: # When XUI_PORT is set, publish the same container port (for example "8080:8080"). - "2053:2053" restart: unless-stopped postgres: image: postgres:16-alpine container_name: 3xui_postgres profiles: ["postgres"] environment: POSTGRES_USER: xui POSTGRES_PASSWORD: xui POSTGRES_DB: xui volumes: - $PWD/pgdata/:/var/lib/postgresql/data restart: unless-stopped