--- title: "Docker Image Examples" --- # Docker Image Examples > This page contains example run configurations for the Ignition Docker image to demonstrate best practices for specified scenarios. ## Deploying an Ephemeral Gateway for Testing The run statement below will launch a container in detached mode `-d`, publishing port `9088` from the host to port `8088` in the container. The container will be named `ignition-test` and use the `8.3.0` image. Finally, the runtime arguments provided will set the Gateway name `-n` to `docker-test` with public address of `localhost` on HTTP port `9088` and HTTPS port `9043`. ```bash docker run -d -p 9088:8088 --name ignition-test inductiveautomation/ignition:8.3.0 -n docker-test -a localhost -h 9088 -s 9043 ``` :::note Multi-line commands For Linux/macOS/WSL, you can use the backslash with multi-line commands for better readability. You can substitute the backtick ` for Powershell and caret ^ for Windows Command prompt, these characters technically "escape" the newline character, so make sure they are the last character on a given line. ::: ## Preserving Gateway State When using containers, it is common for stateful applications (such as the Ignition Gateway) to leverage volumes to persist that state across image updates, container remove/create cycles, etc. This can be done by applying a named volume to the `/usr/local/bin/ignition/data` path within the container. This is especially important if you need to make a change to your container configuration. Since container configurations are immutable, the only way to change it is to stop/remove the old container and start a new one (with a new configuration). The sample run statement will be similar to the one above, but this time with a named volume gw-data attached to `/usr/local/bin/ignition/data` within the container. If the volume doesn't already exist, it will be created automatically. Note the additional `--pull` option to make sure that the `latest` tag is always pulled before running. Without this, the `latest` tag is only pulled if one isn't already present on your system. ```bash docker run -d -p 9088:8088 --name ignition-test \ -v gw-data:/usr/local/bin/ignition/data \ --pull always inductiveautomation/ignition:latest \ -n docker-test -a localhost -h 9088 -s 9043 ``` By using named volumes, you're now able to stop and remove the `ignition-test` container and create a new one with a different configuration. As long as you attach your volume, your Gateway will start up with all of your tags and projects in their previous state. ## Automating the Restore of a Gateway Backup You can automate the restore of a Gateway backup on first-launch of your Gateway container. This allows for having a new Ignition Gateway restore to a known initial state automatically, without waiting for the commissioning steps. To leverage this feature, bind-mount a Gateway backup into the container and then use the `-r` runtime argument to specify the location and command the restore. Additionally, supply the `ACCEPT_IGNITION_EULA=Y` environment variable to accept the Ignition EULA (see the [Licensing](/platform/advanced-deployments/docker-image/docker-image.md#licensing) section) and bypass that Gateway commissioning step. ```bash docker run -d -p 9088:8088 --name ignition-test \ -v gw-data:/usr/local/bin/ignition/data \ -v /path/to/gateway.gwbk:/restore.gwbk \ -e ACCEPT_IGNITION_EULA=Y \ inductiveautomation/ignition:8.3.0 \ -n docker-test -a localhost -h 9088 -s 9043 \ -r /restore.gwbk ``` :::note What if I restart the container The Gateway restore will only apply on a fresh Gateway launch. Subsequent restarts of the container will not restore the indicated Gateway backup. ::: ## Automate the Commissioning of a Fresh Gateway You can automate the commissioning steps that normally require manual user interaction on the very first launch of the Ignition Gateway. By supplying specific [environment variables](/platform/advanced-deployments/docker-image/docker-image.md#environment-variables) , you can seed the commissioning steps with the required information to start the rest of the Gateway automatically. ```bash docker run -d -p 9088:8088 --name ignition-test \ -e ACCEPT_IGNITION_EULA=Y \ -e GATEWAY_ADMIN_PASSWORD=password \ -e IGNITION_EDITION=standard\ inductiveautomation/ignition:8.3.0 \ -n docker-test ``` :::note Reading Environment Variables from a file You can also specify environment variables in the form of `_FILE=/path/to/file` in order to have the environment variable value resolved by reading it from a file. This is helpful for secrets management systems within container orchestrators, such as Docker Swarm and Kubernetes. ::: ## Customizing JVM/Wrapper/Gateway Arguments on Container Launch This example shows how to leverage the supplemental JVM/wrapper args feature. ```bash docker run -d -p 9088:8088 --name args-test \ -e ACCEPT_IGNITION_EULA=Y \ -e GATEWAY_ADMIN_PASSWORD=changeme \ -e IGNITION_EDITION=standard\ inductiveautomation/ignition:8.3.0 \ -n args-test \ -- wrapper.java.initmemory=256 -Dignition.allowunsignedmodules=true \ -Dignition.license.leased-activation-terminate-sessions-on-shutdown=true \ -XX:MaxGCPauseMillis=200 ``` The following demonstrates how to enable the Gateway's Resolve Host Names and Use Proxy Forwarded Headers settings by modifying the entries in the `gateway.xml`: ```bash docker run -d -p 9088:8088 --name ignition-test inductiveautomation/ignition:8.3.0 -n docker-test -a localhost -h 9088 -s 9043 \ -- gateway.resolveHostNames=true gateway.useProxyForwardedHeader=true ``` ## Using Docker Compose A common practice is to leverage [Docker Compose](https://docs.docker.com/compose/) to start your container and bundle the configuration with other services, such as databases and MQTT brokers. Below is an example `docker-compose.yml` file that you can create inside of a new, empty folder. The example below incorporates many of the configurability features mentioned in the various sections above. ```yml title="Compose Example" # Docker Compose Example for inductiveautomation/ignition # Compose Spec: https://github.com/compose-spec/compose-spec/blob/master/spec.md --- services: # Ignition Gateway gateway: image: inductiveautomation/ignition:8.3.0 ports: - 9088:8088 - 9043:8043 volumes: - gw-data:/usr/local/bin/ignition/data # env_file: ignition.env # optionally specify variables in a file, or using `environment:` below environment: - ACCEPT_IGNITION_EULA=Y - GATEWAY_ADMIN_USERNAME=admin - GATEWAY_ADMIN_PASSWORD_FILE=/run/secrets/gateway-admin-password - IGNITION_EDITION=standard - TZ=America/Chicago # see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List secrets: - gateway-admin-password command: > -n docker-test -m 1024 -- wrapper.java.initmemory=512 -Dignition.allowunsignedmodules=true secrets: gateway-admin-password: file: secrets/GATEWAY_ADMIN_PASSWORD volumes: gw-data: ``` Once defined, you can bring up the solution using `docker compose` commands. ![](compose-demo.gif) ## Integrate Third Party Modules After an Upgrade Third party modules installed through the web interface are automatically routed to the [external modules folder](appendix/reference-pages/gateway-configuration-file-reference/gateway-and-gateway-network-parameters/gateway-and-gateway-network-parameters.md#docker-image-external-modules-folder) within the data volume. This means no special consideration is required for these modules when upgrading Ignition to a newer image version. However, if you wish to integrate third party modules such that they cannot be uninstalled by the user, use the following example of how to build a derived image with your modules co-located with the built-in modules under `/usr/local/bin/ignition/user-lib/modules`. :::note If a module is added to the built-in modules location through this method with the same module identifier, that module will route to the external modules folder and effectively "shadow" the built-in module file. For instance, instead of the built-in module loading, the one in the external modules folder with the same module identifier will take precedence. ::: To start, a module subfolder with the modules we are attempting to integrate will be labeled gw-build. The subfolder will also include a Dockerfile. The `docker-compose.yml` file needed for this process is located outside of this subfolder. We will be using a `docker-compose.yml` file similar to the previous example, but instead of using an image tag, we will be using a build tag. ![](third-party-modules.png) ```yml title="docker-compose.yml" services: gateway: build: context: gw-build ## Specify the upstream version to derive from for the build argument in the Docker file. args: IGNITION_VERSION: 8.3.0 ports: - 8088:8088 volumes: - gateway-data:/usr/local/bin/ignition/data environment: ACCEPT_IGNITION_EULA: "Y" GATEWAY_ADMIN_PASSWORD: password IGNITION_EDITION: standard command: > -n Ignition-supp-66195 volumes: gateway-data: ``` The Dockerfile within the gw-build folder will define the derived image by containing a build argument for the Ignition version. Notice this does not give a default version. This is because the version we want to build is specified and passed through our docker-compose definition. Next, we will add a command to copy the module files from this folder to the user-lib module folder inside the new Ignition image. ```yml title="Dockerfile" ARG IGNITION_VERSION FROM inductiveautomation/ignition:${IGNITION_VERSION} COPY *.modl /usr/local/bin/ignition/user-lib/modules/ ``` With these files defined, we can now run `docker compose build` to pull the image, perform all derived image build steps, and create the new image. :::note Since `docker compose build` needs to be run each time a new module is added, you can alternatively add `pull_policy: build` in the yml file to automatically build each time. ::: ## User Migration - Docker Compose The following example uses Docker Compose to demonstrate how to migrate the container user and file ownership from the `root` user to a standard, non-elevated `ignition` user. If you are instead using the command line, see the [next example](#user-migration---command-line) for migrating users. Your environment may vary, depending on how your container is set up. ```yml title="User Migration Example (Docker Compose)" # User Migration Example (Docker Compose) --- services: # Ignition Gateway gateway: image: inductiveautomation/ignition:8.3.0 volumes: - ignition-data:/usr/local/bin/ignition/data ports: - 8088:8088 command: > -n docker-test volumes: ignition-data: ``` 1. Upgrade the container to the latest version by changing the image tag to the version you want to upgrade to: ```yml title="User Migration Example (Docker Compose)" # User Migration Example (Docker Compose) --- services: # Ignition Gateway gateway: image: inductiveautomation/ignition:8.3.0 volumes: - ignition-data:/usr/local/bin/ignition/data ports: - 8088:8088 command: > -n docker-test volumes: ignition-data: ``` 2. Add the `IGNITION_UID=2003` and `IGNITION_GID=2003` environment variables to update the container permissions: ```yml title="User Migration Example (Docker Compose)" # User Migration Example (Docker Compose) --- services: # Ignition Gateway gateway: image: inductiveautomation/ignition:8.3.0 volumes: - ignition-data:/usr/local/bin/ignition/data ports: - 8088:8088 environment: - IGNITION_UID=2003 - IGNITION_GID=2003 command: > -n docker-test volumes: ignition-data: ``` 3. Declare the root user (`user: "0:0"`): ```yml title="User Migration Example (Docker Compose)" # User Migration Example (Docker Compose) --- services: # Ignition Gateway gateway: image: inductiveautomation/ignition:8.3.0 volumes: - ignition-data:/usr/local/bin/ignition/data ports: - 8088:8088 environment: - IGNITION_UID=2003 - IGNITION_GID=2003 user: "0:0" command: > -n docker-test volumes: ignition-data: ``` 4. Save the Docker Compose file, then run `docker compose up -d`. :::note By default, we are using the `-d` option in our Docker command. While you can also run the command without `-d`, the option runs the container in detached mode, allowing the container to run in the background even after closing the terminal. ::: 5. The container will now use the `root` user when it starts up, but will launch Ignition as a standard `ignition` user. All of the files in the ignition-data volume have the proper ownership. We can now remove the `IGNITION_UID` and `IGNITION_GID` environment variables and the `user:"0:0"` override: ```yml title="User Migration Example (Docker Compose)" # User Migration Example (Docker Compose) --- services: # Ignition Gateway gateway: image: inductiveautomation/ignition:8.3.0 volumes: - ignition-data:/usr/local/bin/ignition/data ports: - 8088:8088 command: > -n docker-test volumes: ignition-data: ``` 6. Finally, we can rerun the `docker compose up -d` command to recreate the container. Since we removed the environment variables and updated container permissions, the container will launch with the default user being a standard `ignition` user. 7. To check if the user successfully migrated over, verify the process listing and who the user is for each process using the command `docker compose exec gateway ps aux` in the terminal. Additionally, you can use the command `docker compose exec gateway whoami` to see who the default user for the container is: ![](whoami.png) ## User Migration - Command Line The following example uses the command line to demonstrate how to migrate the container user and file ownership from the `root` user to a standard, non-elevated `ignition` user. If you are instead using Docker Compose, see the [preceding example](#user-migration---docker-compose). Your environment may vary, depending on how your container is set up. The following container is called `example-gw` and is running Ignition version 8.3.0: ```bash title="User Migration Example (Command Line)" docker run --name example-gw -v example-gw-data:/usr/local/bin/ignition/data \ -e IGNITION_EDITION=standard -e ACCEPT_IGNITION_EULA=Y -e GATEWAY_ADMIN_PASSWORD=password \ -p 8088:8088 \ inductiveautomation/ignition:8.3.0 \ -n example-gw ``` 1. Stop and remove your Docker container using the following commands. Keep in mind that you will need to replace `example-gw` with your container name: ```bash title="User Migration Example (Command Line)" # Stop and remove container docker stop example-gw docker rm example-gw ``` 2. Modify the container run configuration to declare the root user using `--user 0:0` (The UID and GID will both be 0): ```bash title="User Migration Example (Command Line)" # Declare the root user docker run --name example-gw --rm -v example-gw-data:/usr/local/bin/ignition/data \ -p 8088:8088 \ --user 0:0 \ inductiveautomation/ignition:8.3.0 \ -n example-gw ``` 3. Update the container permissions by adding the `IGNITION_UID` and `IGNITION_GID` environment variables. You can do this by adding `-e IGNITION_UID=2003 -e IGNITION_GID=2003` after `--user 0:0`: ```bash title="User Migration Example (Command Line)" # Update the container permissions docker run --name example-gw --rm -v example-gw-data:/usr/local/bin/ignition/data \ -p 8088:8088 \ --user 0:0 -e IGNITION_UID=2003 -e IGNITION_GID=2003 \ inductiveautomation/ignition:8.3.0 \ -n example-gw ``` 4. The container's Gateway should now be running under a standard `ignition` user, using a UID of 2003 and a GID of 2003. You can run the following command to count the number of processes running as a standard `ignition` user: ```bash title="User Migration Example (Command Line)" # Count the number of running processes under the ignition user docker exec example-gw pgrep -u 2003 -c ``` :::note There should be 3 processes: * the entrypoint * the Java wrapper * the Java process ::: 5. File ownership should now also belong to the standard `ignition` user. You can use the following command to verify that there are no files owned by any other user aside from the standard `ignition` user: ```bash title="User Migration Example (Command Line)" # Verify file ownership docker exec example-gw bash -c "find /usr/local/bin/ignition ! -user 2003 | wc -l" ``` 6. Once you have verified file ownership and the user the processes are running under, you can now recreate the container against the new image with the default `ignition` user (UID = 2003) and update your Gateway to the latest version: ```bash title="User Migration Example (Command Line)" # Recreate the container docker stop example-gw docker rm example-gw docker run --name example-gw --rm -v example-gw-data:/usr/local/bin/ignition/data \ -p 8088:8088 \ inductiveautomation/ignition:8.3. \ -n example-gw ```