FusionAuth developer image
FusionAuth developer logo
  • Back to site
  • Expert Advice
  • Blog
  • Developers
  • Downloads
  • Account
  • Contact sales
Navigate to...
  • Welcome
  • Getting Started
    • Getting Started
    • 5-minute Setup Guide
      • Overview
      • Docker
      • Fast Path
      • Sandbox
    • Setup Wizard & First Login
    • Register a User and Login
    • Self-service Registration
    • Start and Stop FusionAuth
    • Core Concepts
      • Overview
      • Users
      • Roles
      • Groups
      • Registrations
      • Applications
      • Tenants
      • Identity Providers
      • Authentication/Authorization
      • Integration Points
    • Example Apps
      • Overview
      • Dart
      • Go
      • Java
      • JavaScript
      • .NET Core
      • PHP
      • Python
      • Ruby
    • Tutorials
  • Installation Guide
    • Overview
    • System Requirements
    • Server Layout
    • Cloud
    • Cluster
    • Docker
    • Fast Path
    • Kubernetes
      • Overview
      • Deployment Guide
      • Minikube Setup
      • Amazon EKS Setup
      • Google GKE Setup
      • Microsoft AKS Setup
    • Kickstart™
    • Homebrew
    • Marketplaces
    • Packages
    • Database
    • FusionAuth App
    • FusionAuth Search
    • Common Configuration
  • Migration Guide
    • Overview
    • General
    • Auth0
    • Keycloak
    • Amazon Cognito
    • Firebase
    • Microsoft Azure AD B2C
    • Tutorial
  • Admin Guide
    • Overview
    • Account Portal
    • Config Management
    • Editions and Features
    • Key Rotation
    • Licensing
    • Monitoring
    • Prometheus Setup
    • Proxy Setup
    • Reference
      • Overview
      • Configuration
      • CORS
      • Data Types
      • Hosted Login Pages Cookies
      • Known Limitations
      • Password Hashes
    • Releases
    • Roadmap
    • Search And FusionAuth
    • Securing
    • Switch Search Engines
    • Technical Support
    • Troubleshooting
    • Upgrading
    • WebAuthn
  • Login Methods
    • Identity Providers
      • Overview
      • Apple
      • Epic Games
      • External JWT
        • Overview
        • Example
      • Facebook
      • Google
      • HYPR
      • LinkedIn
      • Nintendo
      • OpenID Connect
        • Overview
        • Amazon Cognito
        • Azure AD
        • Discord
        • Github
      • Sony PlayStation Network
      • Steam
      • Twitch
      • Twitter
      • SAML v2
        • Overview
        • ADFS
        • Azure AD
      • SAML v2 IdP Initiated
        • Overview
        • Okta
      • Xbox
    • OIDC & OAuth 2.0
      • Overview
      • Endpoints
      • Tokens
      • OAuth Modes
    • Passwordless
      • Overview
      • Magic Links
      • WebAuthn & Passkeys
    • SAML v2 IdP
      • Overview
      • Google
      • Zendesk
  • Developer Guide
    • Overview
    • API Gateways
      • Overview
      • ngrok Cloud Edge
    • Client Libraries & SDKs
      • Overview
      • Dart
      • Go
      • Java
      • JavaScript
      • .NET Core
      • Node
      • OpenAPI
      • PHP
      • Python
      • React
      • Ruby
      • Typescript
    • Events & Webhooks
      • Overview
      • Writing a Webhook
      • Securing Webhooks
      • Events
        • Overview
        • Audit Log Create
        • Event Log Create
        • JWT Public Key Update
        • JWT Refresh
        • JWT Refresh Token Revoke
        • Kickstart Success
        • Group Create
        • Group Create Complete
        • Group Delete
        • Group Delete Complete
        • Group Update
        • Group Update Complete
        • Group Member Add
        • Group Member Add Complete
        • Group Member Remove
        • Group Member Remove Complete
        • Group Member Update
        • Group Member Update Complete
        • User Action
        • User Bulk Create
        • User Create
        • User Create Complete
        • User Deactivate
        • User Delete
        • User Delete Complete
        • User Email Update
        • User Email Verified
        • User IdP Link
        • User IdP Unlink
        • User Login Failed
        • User Login Id Dup. Create
        • User Login Id Dup. Update
        • User Login New Device
        • User Login Success
        • User Login Suspicious
        • User Password Breach
        • User Password Reset Send
        • User Password Reset Start
        • User Password Reset Success
        • User Password Update
        • User Reactivate
        • User Reg. Create
        • User Reg. Create Complete
        • User Reg. Delete
        • User Reg. Delete Complete
        • User Registration Update
        • User Reg. Update Complete
        • User Reg. Verified
        • User 2FA Method Add
        • User 2FA Method Remove
        • User Update
        • User Update Complete
    • Guides
      • Overview
      • Authentication Tokens
      • Exposing A Local Instance
      • JSON Web Tokens
      • Key Master
      • Localization and Internationalization
      • Multi-Factor Authentication
      • Multi-Tenant
      • Passwordless
      • Registration-based Email Verification
      • Searching With Elasticsearch
      • Securing Your APIs
      • Silent Mode
      • Single Sign-on
      • Two Factor (pre 1.26)
    • Integrations
      • Overview
      • CleanSpeak
      • Kafka
      • Twilio
    • Plugins
      • Overview
      • Writing a Plugin
      • Custom Password Hashing
    • User Control & Gating
      • Overview
      • Gate Unverified Users
      • Gate Unverified Registrations
      • User Account Lockout
  • Customization
    • Email & Templates
      • Overview
      • Configure Email
      • Email Templates
      • Email Variables
      • Message Templates
    • Lambdas
      • Overview
      • Apple Reconcile
      • Client Cred. JWT Populate
      • Epic Games Reconcile
      • External JWT Reconcile
      • Facebook Reconcile
      • Google Reconcile
      • HYPR Reconcile
      • JWT Populate
      • LDAP Connector Reconcile
      • LinkedIn Reconcile
      • Nintendo Reconcile
      • OpenID Connect Reconcile
      • SAML v2 Populate
      • SAML v2 Reconcile
      • SCIM Group Req. Converter
      • SCIM Group Resp. Convtr.
      • SCIM User Req. Converter
      • SCIM User Resp. Converter
      • Sony PSN Reconcile
      • Steam Reconcile
      • Twitch Reconcile
      • Twitter Reconcile
      • Xbox Reconcile
    • Messengers
      • Overview
      • Generic Messenger
      • Twilio Messenger
    • Themes
      • Overview
      • Examples
      • Helpers
      • Localization
      • Template Variables
  • Premium Features
    • Overview
    • Advanced Registration Forms
    • Advanced Threat Detection
    • Application Specific Themes
    • Breached Password Detection
    • Connectors
      • Overview
      • Generic Connector
      • LDAP Connector
      • FusionAuth Connector
    • Entity Management
    • SCIM
      • Overview
      • Azure AD Client
      • Okta Client
      • SCIM-SDK
    • Self Service Account Mgmt
      • Overview
      • Updating User Data & Password
      • Add Two-Factor Authenticator
      • Add Two-Factor Email
      • Add Two-Factor SMS
      • Add WebAuthn Passkey
      • Customizing
      • Troubleshooting
    • WebAuthn
  • APIs
    • Overview
    • Authentication
    • Errors
    • API Explorer
    • Actioning Users
    • API Keys
    • Applications
    • Audit Logs
    • Connectors
      • Overview
      • Generic
      • LDAP
    • Consents
    • Emails
    • Entity Management
      • Overview
      • Entities
      • Entity Types
      • Grants
    • Event Logs
    • Families
    • Forms
    • Form Fields
    • Groups
    • Identity Providers
      • Overview
      • Links
      • Apple
      • External JWT
      • Epic Games
      • Facebook
      • Google
      • HYPR
      • LinkedIn
      • Nintendo
      • OpenID Connect
      • SAML v2
      • SAML v2 IdP Initiated
      • Sony PlayStation Network
      • Steam
      • Twitch
      • Twitter
      • Xbox
    • Integrations
    • IP Access Control Lists
    • JWT
    • Keys
    • Lambdas
    • Login
    • Message Templates
    • Messengers
      • Overview
      • Generic
      • Twilio
    • Multi-Factor/Two Factor
    • Passwordless
    • Reactor
    • Registrations
    • Reports
    • SCIM
      • Overview
      • SCIM User
      • SCIM Group
      • SCIM EnterpriseUser
      • SCIM Service Provider Config.
    • System
    • Tenants
    • Themes
    • Users
    • User Actions
    • User Action Reasons
    • User Comments
    • WebAuthn
    • Webhooks
  • Release Notes

    Using FusionAuth on Docker

    FusionAuth Docker containers can be used with Docker Compose, Kubernetes, Helm or OpenShift.

    The following example is using Docker Compose. Here are kubernetes installation instructions, which use Helm. Find links for OpenShift and other community supported environments in the FusionAuth Contrib GitHub repo.

    • Docker Compose

      • Installing FusionAuth

      • The Docker Compose Files

    • Docker Services

      • Database Service

      • Search Service

      • The FusionAuth Service

      • Other Services

    • Upgrading

      • Migrations

      • Docker Tags

    • Custom Docker Images

    • Kickstart

    • Plugins

    • Accessing the Host Machine

    • Elasticsearch Production Deployment Configuration

    • Limitations

    Docker Compose

    All of the FusionAuth Docker images may be found on Docker Hub.

    The FusionAuth Docker Compose yaml files may be found on FusionAuth containers repository.

    If you’re looking for a complete configuration to get up and running quickly, use our Docker Compose example. docker-compose.yml will install FusionAuth with ElasticSearch, but you can switch between the different search engines.

    Installing FusionAuth

    To use FusionAuth download the docker-compose.yml and the .env files and then start up the configured containers.

    Download the FusionAuth docker files
    
    curl -o docker-compose.yml https://raw.githubusercontent.com/FusionAuth/fusionauth-containers/master/docker/fusionauth/docker-compose.yml
    curl -o .env https://raw.githubusercontent.com/FusionAuth/fusionauth-containers/master/docker/fusionauth/.env

    Edit these files as needed. The stock .env file will contain the following values, you will want to modify the DATABASE_PASSWORD and ensure the POSTGRES_USER and POSTGRES_PASSWORD values are correct. You may also override any of these values using environment variables.

    The .env file
    
    POSTGRES_USER=postgres
    POSTGRES_PASSWORD=postgres
    DATABASE_USERNAME=fusionauth
    DATABASE_PASSWORD=hkaLBM3RVnyYeYeqE3WI1w2e4Avpy0Wd5O3s3
    ES_JAVA_OPTS="-Xms512m -Xmx512m"
    FUSIONAUTH_APP_MEMORY=512M
    Starting FusionAuth
    
    docker-compose up

    Now you can visit http://localhost:9011 and configure FusionAuth.

    The Docker Compose Files

    The following is the default docker-compose.yml file, which installs FusionAuth.

    docker-compose.yml
    
    version: '3'
    
    services:
      db:
        image: postgres:12.9
        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
        networks:
          - db_net
        restart: unless-stopped
        volumes:
          - db_data:/var/lib/postgresql/data
    
      search:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
        container_name: search
        environment:
          cluster.name: fusionauth
          bootstrap.memory_lock: "true"
          discovery.type: single-node
          ES_JAVA_OPTS: ${ES_JAVA_OPTS}
        healthcheck:
          test: [ "CMD", "curl",  "--fail" ,"--write-out", "'HTTP %{http_code}'", "--silent", "--output", "/dev/null", "http://localhost:9200/" ]
          interval: 5s
          timeout: 5s
          retries: 5
        networks:
          - search_net
        restart: unless-stopped
        ulimits:
          memlock:
            soft: -1
            hard: -1
        volumes:
          - search_data:/usr/share/elasticsearch/data
    
      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_USERNAME}
          DATABASE_PASSWORD: ${DATABASE_PASSWORD}
          FUSIONAUTH_APP_MEMORY: ${FUSIONAUTH_APP_MEMORY}
          FUSIONAUTH_APP_RUNTIME_MODE: development
          FUSIONAUTH_APP_URL: http://fusionauth:9011
          SEARCH_SERVERS: http://search:9200
          SEARCH_TYPE: elasticsearch
    
        networks:
          - db_net
          - search_net
        restart: unless-stopped
        ports:
          - 9011:9011
        volumes:
          - fusionauth_config:/usr/local/fusionauth/config
    
    networks:
      db_net:
        driver: bridge
      search_net:
        driver: bridge
    
    volumes:
      db_data:
      fusionauth_config:
      search_data:

    Docker Services

    In the above example configurations there are three services:

    • database

    • search

    • FusionAuth

    Let’s look at each of these.

    Database Service

    The database service provides a PostgreSQL database for use by FusionAuth.

    You will need to either set the POSTGRES_PASSWORD environment variable in the db service section, or, more ideally, set the value in the host environment and leave it out of the docker-compose.yml file.

    By default this database is not accessible outside of the Docker Compose containers, but you may expose the port if you want to examine the database.

    Review the other properties to ensure they meet your requirements.

    Note: If you plan to use MySQL please review the Limitations for the FusionAuth docker images.

    Search Service

    Versions 6.3.x - 7.17.x are currently supported.

    Later versions may work as well but may not have been tested for compatibility.

    The RAM required by Elasticsearch depends on your login volume and user/entity counts. If you expect to have a few logins per minute and only a few thousand users/entities, 1GB-2GB of RAM will be sufficient. If you have more users/entities as well as logins, please size up accordingly. We recommend running load tests of FusionAuth to help determine the amount of RAM that is required for your needs.

    The FusionAuth Service

    This is the service that runs the FusionAuth application.

    Review the Configuration documentation to customize your deployment. The best way to configure FusionAuth when using Docker is to use environment variables as documented in that link.

    In addition, the port 9011 is mapped between the container and your host machine. This may be modified if you want to run more than one FusionAuth instance or for any other reason.

    Other Services

    You may add other services to the Docker Compose files if needed.

    For example, in development environments it can be helpful to run MailCatcher which provides a local SMTP server. This allows FusionAuth to send transactional emails for account verification, password reset, and others.

    docker-compose.yml with mailcatcher
    
    version: '3'
    
    services:
      db:
        image: postgres:12.9
        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
        networks:
          - db_net
        restart: unless-stopped
        volumes:
          - db_data:/var/lib/postgresql/data
    
      search:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
        container_name: search
        environment:
          cluster.name: fusionauth
          bootstrap.memory_lock: "true"
          discovery.type: single-node
          ES_JAVA_OPTS: ${ES_JAVA_OPTS}
        healthcheck:
          test: [ "CMD", "curl",  "--fail" ,"--write-out", "'HTTP %{http_code}'", "--silent", "--output", "/dev/null", "http://localhost:9200/" ]
          interval: 5s
          timeout: 5s
          retries: 5
        networks:
          - search_net
        restart: unless-stopped
        ulimits:
          memlock:
            soft: -1
            hard: -1
        volumes:
          - search_data:/usr/share/elasticsearch/data
    
      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_USERNAME}
          DATABASE_PASSWORD: ${DATABASE_PASSWORD}
          FUSIONAUTH_APP_MEMORY: ${FUSIONAUTH_APP_MEMORY}
          FUSIONAUTH_APP_RUNTIME_MODE: development
          FUSIONAUTH_APP_URL: http://fusionauth:9011
          SEARCH_SERVERS: http://search:9200
          SEARCH_TYPE: elasticsearch
    
        networks:
          - db_net
          - search_net
          - mailcatcher_net
        restart: unless-stopped
        ports:
          - 9011:9011
        volumes:
          - fusionauth_config:/usr/local/fusionauth/config
    
      mailcatcher:
        image: yappabe/mailcatcher
        ports:
          - "1025:1025"
          - "1080:1080"
        networks:
          - mailcatcher_net
    
    networks:
      db_net:
        driver: bridge
      search_net:
        driver: bridge
      mailcatcher_net:
        driver: bridge
    
    volumes:
      db_data:
      fusionauth_config:
      search_data:

    Below is a functional configuration on the tenant email tab based on the above configuration file:

    Tenant Setting With MailCatcher

    This a view of the Mailcatcher client.

    Mailcatcher Client View

    Upgrading

    To upgrade FusionAuth when running with docker-compose:

    1. Stop the instance: docker-compose down.

    2. Modify the docker-compose.yml file to point to the version of FusionAuth you want. You can see available tags.

    3. Start it up: docker-compose up.

    4. Login to the administrative UI.

    Migrations

    If there were database migrations required, what happens on an upgrade depends on two settings: the runtime mode and the silent mode.

    Prior to version 1.19.0, migration behavior was different. See below for more.

    If silent mode is set to true, then database migrations will automatically be performed.

    If silent mode is false and the runtime mode is set to development, then the maintenance mode screen will pop up and you will be prompted to complete the migrations there.

    In all other cases the migrations will not be applied, and you’ll have to perform them yourself. If you want to manage your own database upgrades, performing the SQL migrations out of band with another tool or process is a good option.

    Table 1. When Are Database Migrations Applied
    Runtime Mode Silent Mode Migration Behavior

    development

    true

    Migration applied automatically

    development

    false

    Maintenance mode UI displayed, user prompted to run migrations

    production

    true

    Migration applied automatically

    production

    false

    Migration never applied by FusionAuth, must be applied out of band

    See the configuration reference or the silent mode guide for more information. To apply the database migrations out of band see the database upgrade documentation.

    Prior to 1.19

    If the installation is in production mode, apply the migrations out of band.

    When running in development runtime mode, silent mode was enabled based upon the presence of environment variables, such as the database user, and could not explicitly be enabled or disabled.

    Docker Tags

    The Docker Compose file references the latest tag, but that tag is not dynamic. It is only the latest at a point in time. To get the most recently released image, you have a couple of options.

    • Edit the Docker Compose file and specify a specific version. This is a good idea for a production deployment.

    • Remove the old image first: docker rmi <old image id>. This command may prompt you to remove containers using that image. Since all state is stored in the database, you can safely remove the containers. Then, when you restart Docker Compose, the latest image will be retrieved.

    • Pull the latest image with this command: docker pull fusionauth/fusionauth-app:latest.

    Custom Docker Images

    If you want to build your own image starting with our base image, start with the fusionauth/fusionauth-app image. Just as the FusionAuth Docker image is based on the ubuntu:focal image, you can build a Docker file which is based on the fusionauth:fusionauth-app image. This can be useful if you want to automatically install a password hashing plugin, configuration file, or other customization.

    Here’s the FusionAuth application Docker image file as a reference.

    The FusionAuth Docker file
    
    #
    # FusionAuth App Dockerfile
    #
    # Build:
    #   > docker pull ubuntu:jammy
    #   > docker buildx build --platform=linux/arm64 -t fusionauth/fusionauth-app:1.43.0 .
    #   > docker buildx build --platform=linux/arm64 -t fusionauth/fusionauth-app:latest .
    #
    # Note: Substiture your target platform architecture. The above example is targetting a 64-bit ARM platform.
    #       To target an Intel based platform use --platform=linux/amd64.
    #
    # Run:
    #  > docker run -p 9011:9011 -it fusionauth/fusionauth-app
    #
    # Publish:
    #   > docker push fusionauth/fusionauth-app:1.43.0
    #   > docker push fusionauth/fusionauth-app:latest
    #
    
    ###### Setup the java and fusionauth-app base #####################################################
    FROM --platform=$BUILDPLATFORM ubuntu:jammy as build
    
    ARG BUILDPLATFORM
    ARG FUSIONAUTH_VERSION=1.43.0
    ARG JDK_MODULES=java.base,java.compiler,java.desktop,java.instrument,java.logging,java.management,java.naming,java.rmi,java.security.jgss,java.security.sasl,java.scripting,java.sql,java.xml.crypto,jdk.attach,jdk.crypto.ec,jdk.dynalink,jdk.jcmd,jdk.jdi,jdk.localedata,jdk.jpackage,jdk.unsupported,jdk.zipfs
    ARG TARGETPLATFORM
    ARG TARGETARCH
    RUN printf "Building on ${BUILDPLATFORM} for ${TARGETPLATFORM} (${TARGETARCH})."
    RUN case "${BUILDPLATFORM}" in \
        linux/arm64)\
            BUILD_JAVA_SUM="2e3c19c1707205c6b90cc04b416e8d83078ed98417d5a69dce3cf7dc0d7cfbca";\
            BUILD_JAVA_URL="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.3_7.tar.gz";\
            ;;\
        linux/amd64)\
            BUILD_JAVA_SUM="81f5bed21077f9fbb04909b50391620c78b9a3c376593c0992934719c0de6b73";\
            BUILD_JAVA_URL="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_x64_linux_hotspot_17.0.3_7.tar.gz";\
            ;;\
        *)\
            printf "Unsupported build platform arch: ${BUILDPLATFORM}";\
            exit 1;\
            ;;\
        esac \
        && case "${TARGETARCH}" in \
        arm64)\
            JAVA_SUM="2e3c19c1707205c6b90cc04b416e8d83078ed98417d5a69dce3cf7dc0d7cfbca";\
            JAVA_URL="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.3_7.tar.gz";\
            ;;\
        arm)\
            JAVA_SUM="d76c462f44c9f306a0fe4468a0218a261ab152f358a8fb55ec80865bf35e2c41";\
            JAVA_URL="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_arm_linux_hotspot_17.0.3_7.tar.gz";\
            ;;\
        ppc64le)\
            JAVA_SUM="a04587018c9719dca21073f19d56b335c4985f41afe7d99b24852c1a94b917e5";\
            JAVA_URL="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.3_7.tar.gz";\
            ;;\
        s390x)\
            JAVA_SUM="d9456cdf9719f9d8a11f26b2dd176cd6a8478d96ced09396765c7473482bc7f1";\
            JAVA_URL="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.3_7.tar.gz";\
            ;;\
        amd64)\
            JAVA_SUM="81f5bed21077f9fbb04909b50391620c78b9a3c376593c0992934719c0de6b73";\
            JAVA_URL="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.3%2B7/OpenJDK17U-jdk_x64_linux_hotspot_17.0.3_7.tar.gz";\
            ;;\
        *)\
            printf "Unsupported arch: ${TARGETARCH}";\
            exit 1;\
            ;;\
        esac \
        && apt-get update \
        && apt-get install -y curl unzip \
        && mkdir -p /tmp/openjdk \
        && mkdir -p /tmp/build/openjdk \
        && curl -LfsSo /tmp/build/openjdk.tar.gz "${BUILD_JAVA_URL}" \
        && echo "${BUILD_JAVA_SUM} */tmp/build/openjdk.tar.gz" | sha256sum -c - \
        && curl -LfsSo /tmp/openjdk.tar.gz "${JAVA_URL}" \
        && echo "${JAVA_SUM} */tmp/openjdk.tar.gz" | sha256sum -c - \
        && cd /tmp/build/openjdk \
        && tar -xf /tmp/build/openjdk.tar.gz --strip-components=1 \
        && cd /tmp/openjdk \
        && tar -xf /tmp/openjdk.tar.gz --strip-components=1 \
        && /tmp/build/openjdk/bin/jlink --compress=2 \
               --module-path /tmp/openjdk/jmods/ \
               --add-modules ${JDK_MODULES} \
               --output /opt/openjdk \
        && curl -LfsSo /tmp/fusionauth-app.zip https://files.fusionauth.io/products/fusionauth/${FUSIONAUTH_VERSION}/fusionauth-app-${FUSIONAUTH_VERSION}.zip \
        && mkdir -p /usr/local/fusionauth/fusionauth-app \
        && unzip -nq /tmp/fusionauth-app.zip -d /usr/local/fusionauth
    
    ###### Use Ubuntu latest and only copy in what we need to reduce the layer size ###################
    FROM ubuntu:jammy
    RUN useradd -d /usr/local/fusionauth -U fusionauth
    COPY --chown=fusionauth:fusionauth --from=build /opt/openjdk /opt/openjdk
    COPY --chown=fusionauth:fusionauth --from=build /usr/local/fusionauth /usr/local/fusionauth
    
    ###### Connect the log file to stdout #############################################################
    RUN mkdir -p /usr/local/fusionauth/logs \
      && touch /usr/local/fusionauth/logs/fusionauth-app.log \
      && ln -sf /dev/stdout /usr/local/fusionauth/logs/fusionauth-app.log
    
    ###### Start FusionAuth App #######################################################################
    LABEL description="Create an image running FusionAuth App. Installs FusionAuth App"
    LABEL maintainer="FusionAuth <dev@fusionauth.io>"
    EXPOSE 9011
    USER fusionauth
    ENV FUSIONAUTH_USE_GLOBAL_JAVA=1
    ENV JAVA_HOME=/opt/openjdk
    ENV PATH=$PATH:$JAVA_HOME/bin
    CMD ["/usr/local/fusionauth/fusionauth-app/bin/start.sh"]

    Here is additional Docker documentation.

    Kickstart

    Using Docker with Kickstart is a powerful combination. Using these technologies together lets you:

    • Configure and share development environments

    • Create replicable bug reports

    • Spin up auth instances with a well known, versioned set of data for continuous integration and testing

    All the normal limitations of Kickstart apply (the Kickstart will not run if the database has already been set up with an API key, for example).

    It’s easy to get started with Kickstart, but you’ll need to tweak your Docker Compose files a bit. Before you begin, you’ll need a valid kickstart.json file. Note that this file could be called anything, kickstart.json is simply a convention. Check out the Kickstart documentation for more information on writing one.

    Once you have a valid kickstart.json file, create a subdirectory in the location of your docker-compose.yml file. It can be named anything; this documentation will use a directory called kickstart. Next, you’ll mount this directory and set the FUSIONAUTH_APP_KICKSTART_FILE variable in the docker-compose.yml file.

    Here are the steps to do so:

    • In the volumes: section of the fusionauth service, add - ./kickstart:/usr/local/fusionauth/kickstart.

    • Modify .env and add the Kickstart configuration variable: FUSIONAUTH_APP_KICKSTART_FILE=/usr/local/fusionauth/kickstart/kickstart.json. This path should be what the Docker container expects, not the path on the host.

    • Configure docker-compose.yml to pass the environment variable set by .env to the container. Do this by adding FUSIONAUTH_APP_KICKSTART_FILE: ${FUSIONAUTH_APP_KICKSTART_FILE} to the environment section of the fusionauth service.

    • docker-compose up

    The following is an example docker-compose.yml file configuring FusionAuth to run the commands in a kickstart.json at startup.

    Example Docker compose file for running Kickstart
    
    version: '3'
    
    services:
      db:
        image: postgres:12.9
        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
        networks:
          - db_net
        restart: unless-stopped
        volumes:
          - db_data:/var/lib/postgresql/data
    
      search:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
        container_name: search
        environment:
          cluster.name: fusionauth
          bootstrap.memory_lock: "true"
          discovery.type: single-node
          ES_JAVA_OPTS: ${ES_JAVA_OPTS}
        healthcheck:
          test: [ "CMD", "curl",  "--fail" ,"--write-out", "'HTTP %{http_code}'", "--silent", "--output", "/dev/null", "http://localhost:9200/" ]
          interval: 5s
          timeout: 5s
          retries: 5
        networks:
          - search_net
        restart: unless-stopped
        ulimits:
          memlock:
            soft: -1
            hard: -1
        volumes:
          - search_data:/usr/share/elasticsearch/data
    
      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_USERNAME}
          DATABASE_PASSWORD: ${DATABASE_PASSWORD}
          FUSIONAUTH_APP_MEMORY: ${FUSIONAUTH_APP_MEMORY}
          FUSIONAUTH_APP_RUNTIME_MODE: development
          FUSIONAUTH_APP_URL: http://fusionauth:9011
          SEARCH_SERVERS: http://search:9200
          SEARCH_TYPE: elasticsearch
          FUSIONAUTH_APP_KICKSTART_FILE: ${FUSIONAUTH_APP_KICKSTART_FILE}
    
        networks:
          - db_net
          - search_net
        restart: unless-stopped
        ports:
          - 9011:9011
        volumes:
          - fusionauth_config:/usr/local/fusionauth/config
          - ./kickstart:/usr/local/fusionauth/kickstart
    
    networks:
      db_net:
        driver: bridge
      search_net:
        driver: bridge
    
    volumes:
      db_data:
      fusionauth_config:
      search_data:

    After running docker-compose up you should see a line like this in the output:

    FusionAuth log messages indicating Kickstart has succeeded
    
    io.fusionauth.api.service.system.kickstart.KickstartRunner - Summary

    This indicates that Kickstart completed and provides a summary of the configuration changes made by it.

    You may also want to check out the Isolated Docker Setups if you want the ability to rapidly stand up different versions and configurations of FusionAuth.

    If you want to test changes to your Kickstart file, you’ll need to delete your volumes each time. Kickstart won’t run except on a brand new install. If there is any data in the database, it won’t proceed.

    This will delete all data in your docker instance.

    Deleting the volumes
    
    docker-compose down -v

    Plugins

    You can mount a directory containing a plugin to your Docker container.

    Here are the steps to do so:

    • In the volumes: section of the fusionauth service, add - ./plugins:/usr/local/fusionauth/plugins.

    • Copy your plugin jar file, created by following the instructions, to your plugins directory on the host.

    • docker-compose up

    The following is an example docker-compose.yml file configuring FusionAuth to scan for plugins at startup.

    Example Docker compose file for installing a plugin
    
    
    version: '3'
    
    services:
      db:
        image: postgres:12.9
        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
        networks:
          - db_net
        restart: unless-stopped
        volumes:
          - db_data:/var/lib/postgresql/data
    
      search:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
        container_name: search
        environment:
          cluster.name: fusionauth
          bootstrap.memory_lock: "true"
          discovery.type: single-node
          ES_JAVA_OPTS: ${ES_JAVA_OPTS}
        healthcheck:
          test: [ "CMD", "curl",  "--fail" ,"--write-out", "'HTTP %{http_code}'", "--silent", "--output", "/dev/null", "http://localhost:9200/" ]
          interval: 5s
          timeout: 5s
          retries: 5
        networks:
          - search_net
        restart: unless-stopped
        ulimits:
          memlock:
            soft: -1
            hard: -1
        volumes:
          - search_data:/usr/share/elasticsearch/data
    
      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_USERNAME}
          DATABASE_PASSWORD: ${DATABASE_PASSWORD}
          FUSIONAUTH_APP_MEMORY: ${FUSIONAUTH_APP_MEMORY}
          FUSIONAUTH_APP_RUNTIME_MODE: development
          FUSIONAUTH_APP_URL: http://fusionauth:9011
          SEARCH_SERVERS: http://search:9200
          SEARCH_TYPE: elasticsearch
    
        networks:
          - db_net
          - search_net
        restart: unless-stopped
        ports:
          - 9011:9011
        volumes:
          - fusionauth_config:/usr/local/fusionauth/config
          - ./plugins:/usr/local/fusionauth/plugins
    
    networks:
      db_net:
        driver: bridge
      search_net:
        driver: bridge
    
    volumes:
      db_data:
      fusionauth_config:
      search_data:

    After running docker-compose up you should see a line like this in the output:

    FusionAuth log messages indicating a plugin has been successfully installed
    
    INFO  io.fusionauth.api.plugin.guice.PluginModule - Installing plugin [com.mycompany.fusionauth.plugins.guice.MyExampleFusionAuthPluginModule]
    INFO  io.fusionauth.api.plugin.guice.PluginModule - Plugin successfully installed

    Such output indicates that the plugin has been installed and can be used.

    Accessing the Host Machine

    The default FusionAuth Docker configuration sets up the network using the bridge configuration. This means that all the hosts defined by docker-compose can access each other. However, it means that any applications running on your host machine cannot be accessed by FusionAuth using localhost.

    This is typically only an issue when FusionAuth is accessing resources outside of the Docker network to, for example, send email or request a webhook. If a Rails application is running locally on a Mac and you want FusionAuth, running in Docker, to send a webhook payload to it, localhost won’t work.

    In this situation, do one of the following:

    • Use host.docker.internal as the hostname; this works on macOS and Windows hosts

    • Run a container with your application in Docker

    • Install FusionAuth on the host machine, using FastPath or another method

    Modifying FusionAuth to use other Docker networking schemes such as host may work, but isn’t fully tested or supported.

    Elasticsearch Production Deployment Configuration

    Elasticsearch has a few runtime requirements that may not be met by default on your host platform. Please review the Elasticsearch Docker production mode guide for more information.

    For example if startup is failing and you see the following in the logs, you will need to increase vm.max_map_count on your host VM.

    The log message when max_map_count is too low
    
    2018-11-22T12:32:06.779828954Z Nov 22, 2018 12:32:06.779 PM ERROR c.inversoft.maintenance.search.ElasticsearchSilentConfigurationWorkflowTask
      - Silent configuration was unable to complete search configuration. Entering maintenance mode. State [SERVER_DOWN]
    
    2018-11-22T13:00:05.346558595Z ERROR: [2] bootstrap checks failed
    2018-11-22T13:00:05.346600195Z [1]: memory locking requested for elasticsearch process but memory is not locked
    2018-11-22T13:00:05.346606495Z [2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

    Limitations

    Due to Oracle licensing restrictions, the docker images published on Docker Hub do not contain the necessary software to connect to a MySQL database.

    If you wish to use MySQL, you’ll need to build a custom container that includes the MySQL Connector JAR file. Here is an example container definition that uses the FusionAuth image as a base layer and adds the MySQL connector.

    Example Dockerfile which downloads the MySQL connector
    
    #
    # FusionAuth App Dockerfile including the MySQL connector
    #
    # Note:
    # -----------------------------------------------------------------------------
    # The MySQL JDBC connector is not bundled with FusionAuth due to the GPL
    # license terms under which Oracle publishes this software.
    #
    # Because of this restriction, you will need to build a docker image for your
    # use that contains the MySQL JDBC connector in order to connect to a MySQL
    # database at runtime.
    
    # Source: https://github.com/mysql/mysql-connector-j
    # License: https://github.com/mysql/mysql-connector-j/blob/release/8.0/LICENSE
    # Homepage: https://dev.mysql.com/doc/connector-j/8.0/en/
    #
    # If you choose to build a Docker image containing this connector, ensure you
    # aware and in compliance with the license under which the MySQL JDBC connector
    # is provided.
    #
    # This file is provided as an example only.
    # -----------------------------------------------------------------------------
    #
    # Build:
    #   > docker build -t fusionauth/fusionauth-app-mysql:1.43.0-{integration} .
    #   > docker build -t fusionauth/fusionauth-app-mysql:latest .
    #
    # Run:
    #  > docker run -p 9011:9011 -it fusionauth/fusionauth-app-mysql
    #
    
    FROM fusionauth/fusionauth-app:1.43.0
    ADD --chown=fusionauth:fusionauth https://search.maven.org/remotecontent?filepath=mysql/mysql-connector-java/8.0.30/mysql-connector-java-8.0.30.jar /usr/local/fusionauth/fusionauth-app/lib

    Feedback

    How helpful was this page?

    See a problem?

    File an issue in our docs repo

    Have a question or comment to share?

    Visit the FusionAuth community forum.

    © 2023 FusionAuth
    Subscribe for developer updates