Docker
This page explains how to install FusionAuth using Docker. A typical FusionAuth install includes three services: fusionauth-app, a database, and a search service:

For Kubernetes install instructions, see Install with Kubernetes.
For an advanced discussion of FusionAuth Docker image customization, see Customize Docker Images.
Prerequisites#
The instructions below require the following prerequisites:
- Docker 23 or later
- On macOS and Windows, one of the following container management tools:
- OrbStack (to use Orbstack for
docker composecommands after install, rundocker context use orbstack) - Podman (in the commands below, replace
dockerwithpodman) - Docker desktop
- OrbStack (to use Orbstack for
Install#
Use the steps below to install FusionAuth using Docker Compose with the configuration files in the fusionauth-containers repository:
-
Download the
docker-compose.ymland.envfiles:$ curl -o docker-compose.yml https://raw.githubusercontent.com/FusionAuth/fusionauth-containers/main/docker/fusionauth/docker-compose.ymlFulldocker-compose.yamlexampledocker-compose.yml
services: # # Required services (database and FusionAuth) # # Postgresql is the default database. You can swap this out for MySQL if you prefer. db: image: postgres:16.0-bookworm environment: PGDATA: /var/lib/postgresql/data/pgdata POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} healthcheck: test: [ "CMD-SHELL", "pg_isready -U postgres" ] interval: 5s timeout: 5s retries: 5 restart: unless-stopped volumes: - db_data:/var/lib/postgresql/data # This is the main FusionAuth application. fusionauth: image: fusionauth/fusionauth-app:latest depends_on: db: condition: service_healthy search: condition: service_healthy environment: DATABASE_URL: jdbc:postgresql://db:5432/fusionauth DATABASE_ROOT_USERNAME: ${POSTGRES_USER} DATABASE_ROOT_PASSWORD: ${POSTGRES_PASSWORD} DATABASE_USERNAME: ${DATABASE_USER} DATABASE_PASSWORD: ${DATABASE_PASSWORD} FUSIONAUTH_APP_KICKSTART_FILE: ${FUSIONAUTH_APP_KICKSTART_FILE} FUSIONAUTH_APP_MEMORY: ${FUSIONAUTH_APP_MEMORY} FUSIONAUTH_APP_RUNTIME_MODE: ${FUSIONAUTH_APP_RUNTIME_MODE} FUSIONAUTH_APP_URL: http://fusionauth:9011 SEARCH_SERVERS: http://search:9200 SEARCH_TYPE: ${FUSIONAUTH_SEARCH_TYPE} FUSIONAUTH_APP_INSTALLATION_SOURCE: fusionauth-containers healthcheck: test: curl --silent --fail http://localhost:9011/api/status -o /dev/null -w "%{http_code}" interval: 5s timeout: 5s retries: 5 restart: unless-stopped ports: - 9011:9011 volumes: - fusionauth_config:/usr/local/fusionauth/config - ${FUSIONAUTH_LOCAL_KICKSTART_DIRECTORY}:/usr/local/fusionauth/kickstart - ${FUSIONAUTH_LOCAL_PLUGIN_DIRECTORY}:/usr/local/fusionauth/plugins # Open Search isn't technically required, but the `fusionauth` service currently depends on it, so we start it here. # You can change the search engine backend to `database` in the `.env` file if you would prefer to use that. # Then you can remove the search dependency above and disable this service. search: image: opensearchproject/opensearch:2.11.0 environment: cluster.name: fusionauth discovery.type: single-node node.name: search plugins.security.disabled: "true" bootstrap.memory_lock: "true" OPENSEARCH_JAVA_OPTS: ${OPENSEARCH_JAVA_OPTS} healthcheck: interval: 10s retries: 80 test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:9200/ restart: unless-stopped ulimits: memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 ports: - 9200:9200 # REST API - 9600:9600 # Performance Analyzer volumes: - search_data:/usr/share/opensearch/data # # Optional services # # Caddy can be used as a proxy to FusionAuth. caddy: image: caddy profiles: - caddy depends_on: - fusionauth restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data - caddy_config:/config # Mailcatcher is a nice SMTP server that can be used for development and testing. You'll need to configure FusionAuth # to use Mailcatcher (or use a Kickstart file that points the SMTP configuration to localhost:1025). mailcatcher: image: sj26/mailcatcher profiles: - mailcatcher ports: - "1025:1025" - "1080:1080" healthcheck: interval: 10s retries: 80 test: wget -q -O /dev/null http://mailcatcher:1080/ # Zookeeper is needed for Kafka zookeeper: image: confluentinc/cp-zookeeper:latest profiles: - kafka environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 ports: - 2181:2181 # Kafka can be used for Webhooks rather than HTTP. You'll need to configure FusionAuth to use Kafka (or use a # Kickstart file that enables Kafka). kafka: image: confluentinc/cp-kafka:latest profiles: - kafka depends_on: - zookeeper ports: - 9092:9092 environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 # Cleanspeak provides filtering of usernames and profile data to prevent profanity and other unwanted content. You'll # need a Cleanspeak license to enable this service. cleanspeak: image: cleanspeak/cleanspeak-app:latest profiles: - cleanspeak depends_on: db: condition: service_healthy search: condition: service_healthy environment: DATABASE_URL: jdbc:postgresql://db:5432/cleanspeak DATABASE_ROOT_USERNAME: ${POSTGRES_USER} DATABASE_ROOT_PASSWORD: ${POSTGRES_PASSWORD} DATABASE_USERNAME: ${DATABASE_USER} DATABASE_PASSWORD: ${DATABASE_PASSWORD} CLEANSPEAK_APP_MEMORY: ${CLEANSPEAK_APP_MEMORY} LICENSE_ID: ${CLEANSPEAK_LICENSE_ID} SEARCH_SERVERS: http://search:9200 restart: unless-stopped ports: - 8001:8001 volumes: - cs_config:/usr/local/cleanspeak/config # OpenTelemetry can be used to collect metrics from FusionAuth and push them to Prometheus or other systems. You might need # to configure OpenTelemetry by editing the opentelementy-collector-config.yml file. opentelemetry: image: otel/opentelemetry-collector profiles: - opentelemetry depends_on: - fusionauth ports: - 8889:8889 - 4318:4318 volumes: - ${OPENTELEMETRY_COLLECTOR_CONFIG_FILE}:/etc/opentelemetry/collector-config.yml command: [ "--config=/etc/opentelemetry/collector-config.yml" ] # Prometheus can be used to monitor FusionAuth and can be used with OpenTelemetry or directly. Depending on the way you want to # use Prometheus, you might need to change the PROMETHEUS_CONFIG_FILE variable to point to a different configuration file or # edit the configuration files as needed. prometheus: image: prom/prometheus profiles: - prometheus depends_on: - fusionauth ports: - 9090:9090 volumes: - ${PROMETHEUS_CONFIG_FILE}:/etc/prometheus/prometheus.yml - ${PROMETHEUS_RULES_FILE}:/etc/prometheus/rules.yml - prometheus_data:/prometheus # Alertmanager can be used in conjunction with Prometheus to handle errors that are collected. alertmanager: image: prom/alertmanager:v0.28.1 profiles: - alertmanager depends_on: - prometheus ports: - 9093:9093 volumes: - ${ALERTMANAGER_CONFIG_FILE}:/etc/alertmanager/alertmanager-config.yml volumes: caddy_config: caddy_data: cs_config: db_data: fusionauth_config: prometheus_data: search_data:$ curl -o .env https://raw.githubusercontent.com/FusionAuth/fusionauth-containers/main/docker/fusionauth/.envFull.envexample.env
ALERTMANAGER_CONFIG_FILE=./monitoring/alertmanager-config.yml CLEANSPEAK_APP_MEMORY=512M CLEANSPEAK_LICENSE_ID=insert-license-id-here DATABASE_USER=fusionauth DATABASE_PASSWORD=hkaLBM3RVnyYeYeqE3WI1w2e4Avpy0Wd5O3s3 FUSIONAUTH_APP_KICKSTART_FILE=/usr/local/fusionauth/kickstart/kickstart.json FUSIONAUTH_APP_MEMORY=512M FUSIONAUTH_APP_RUNTIME_MODE=development FUSIONAUTH_LOCAL_KICKSTART_DIRECTORY=./kickstart FUSIONAUTH_LOCAL_PLUGIN_DIRECTORY=./plugins FUSIONAUTH_SEARCH_TYPE=elasticsearch OPENSEARCH_JAVA_OPTS="-Xms512m -Xmx512m" OPENTELEMETRY_COLLECTOR_CONFIG_FILE=./monitoring/opentelemetry-collector-config.yml POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres PROMETHEUS_CONFIG_FILE=./monitoring/prometheus-config.yml PROMETHEUS_RULES_FILE=./monitoring/prometheus-rules.yml -
Modify
DATABASE_PASSWORDand ensure thePOSTGRES_USERandPOSTGRES_PASSWORDvalues are correct. You may also override any of these values using environment variables. -
Start the FusionAuth docker container:
$ docker compose up -d -
Wait until all networks, volumes, and containers show a green status of Healthy, Started, or Created. This may take a few minutes, depending on your network speed and cached dependencies.
-
Visit http://localhost:9011 to access the Admin UI.
-
Congratulations, you have a working instance of FusionAuth!
Next steps#
To set up login for an application, see our First Time Setup guide.