🤖 For AI agents: The complete documentation index is available at /docs/llms.txt. A markdown version of this page is available at /docs/get-started/download-and-install/docker.md.

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

A diagram depicting three services in a docker container: a FusionAuth service, a database service, and a search service.

A diagram depicting three services in a docker container: a FusionAuth service, a database service, 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 compose commands after install, run docker context use orbstack)
    • Podman (in the commands below, replace docker with podman)
    • Docker desktop

Install#

Use the steps below to install FusionAuth using Docker Compose with the configuration files in the fusionauth-containers repository:

  1. Download the docker-compose.yml and .env files:

    $ curl -o docker-compose.yml https://raw.githubusercontent.com/FusionAuth/fusionauth-containers/main/docker/fusionauth/docker-compose.yml
    
    Full docker-compose.yaml example

    docker-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/.env
    
    Full .env example

    .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
  2. Modify DATABASE_PASSWORD and ensure the POSTGRES_USER and POSTGRES_PASSWORD values are correct. You may also override any of these values using environment variables.

  3. Start the FusionAuth docker container:

    $ docker compose up -d
    
  4. 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.

  5. Visit http://localhost:9011 to access the Admin UI.

  6. Congratulations, you have a working instance of FusionAuth!

Next steps#

To set up login for an application, see our First Time Setup guide.