# Docker image now defaults to non-root user

**URL:** <https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784>\
**Category:** Ignition Early Access\
**Tags:** docker\
**Created:** [February 13, 2023, 6:04pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784 "2023-02-13T18:04:59Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [February 13, 2023, 6:04pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/1 "2023-02-13T18:04:59Z")

</div>

Greetings! I wanted to announce that the container image for the next nightly (which will eventually end up in the 8.1.26 release) contains changes to the default user/group that is used to launch Ignition.

The default user is now `ignition` with UID/GID of `2003`. You'll have to perform a migration in order to successfully transition your existing data volumes, otherwise you may encounter an error such as this one below:

```auto
init | 2023/02/13 11:50:21 | Creating init.properties file
init | 2023/02/13 11:50:21 | Detected Ignition Volume from prior version (8.1.24), running Upgrader...
java.io.FileNotFoundException: /usr/local/bin/ignition/data/ignition.conf (Permission denied)
...

```

The above is one such manifestation of the new `ignition` user being unable to modify files that are owned by `root` within an attached data volume. You can choose between at least a couple options:

- Explicitly set the user for the container to be `0:0` (i.e. `root` user:group), overriding the new default. You can do this with either `--user 0:0` in your `docker run` or the [user](https://github.com/compose-spec/compose-spec/blob/master/spec.md#user) directive in Compose. Note that you're not getting any of the advantages here of non-root execution.
- Migrate your data volume by temporarily launching a container with `--user 0:0` and environment variables `IGNITION_UID=2003` and `IGNITION_GID=2003`. This will leverage the existing root step-down functionality and remap your data volume file ownership to the target UID/GID that matches the new default user. After startup, you can stop the container and re-launch without any explicit user or UID/GID environment variable overrides in the future.

We're working on updating the docs site with more detailed guidance on the migration that should be available for the final release.

Let me know if you have any questions!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 13, 2023, 6:16pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/2 "2023-02-13T18:16:12Z")

</div>

So, `AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_RAW` in an override?

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [February 13, 2023, 6:35pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/3 "2023-02-13T18:35:53Z")

</div>

If you also need these capabilities (for sub-1024 port binding as non-root user and raw socket use for ICMP, respectively), yes, you'd specify those in your container config.

refs:

- [Docker run reference | Docker Documentation](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)
- [compose-spec/spec.md at master · compose-spec/compose-spec · GitHub](https://github.com/compose-spec/compose-spec/blob/master/spec.md#cap_add)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 13, 2023, 6:53pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/4 "2023-02-13T18:53:16Z")

</div>

My point was that those should be the default--your image should include that in an override. IMNSHO. { Well, arguably, Ignition's default SystemD unit file should have it. }

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [February 13, 2023, 7:50pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/5 "2023-02-13T19:50:50Z")

</div>

I should clarify that the Docker image launches that gateway directly, no systemd involved (as is typical in most container images). The capabilities that a container gets when launched is controlled by the container runtime--see some info [here](https://docs.docker.com/engine/security/#linux-kernel-capabilities). There isn't a way to "request" default capabilities within the OCI image definition that I'm aware of.

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [March 27, 2023, 6:30pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/6 "2023-03-27T18:30:14Z")

</div>

Tiny addendum: We just upgraded over this bump today and it broke us since we build a derivative image with git tools and our old Dockerfile was expecting root. After double-checking that things run as `ignition` normally, just adjusted our Dockerfile to look like this:

```auto
FROM inductiveautomation/ignition:8.1.26
USER root
RUN apt-get update && \
    apt-get install -y git && \
    rm -rf /var/lib/apt/lists/*
USER ignition

```

If I was more thoroughly adept with Docker I would've expected this, but I'm not and I didn't. Thankfully someone else on our team knows more Docker and set me straight quickly.

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [March 27, 2023, 7:03pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/7 "2023-03-27T19:03:58Z")

</div>

There is migration guidance for existing volumes (that are being upgraded to 8.1.26) in our documentation here: [Docker Image - Ignition User Manual 8.1 - Ignition Documentation](https://docs.inductiveautomation.com/display/DOC81/Docker+Image)

@justin.brzozoski, agreed that for derived images going forward, you'll need to temporarily set `USER root` to do things like OS package updates and then set `USER ignition` at the end. Just be careful if you do anything that creates files within the Ignition installation, you'll want to make sure that those files remain chown'd to `ignition:ignition`. 👍

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [March 27, 2023, 7:34pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/8 "2023-03-27T19:34:51Z")

</div>

Not out of the woods yet ... we have our developer stations set up such that data/projects is mounted to a working directory on the host system and I just ran into this:

```auto
> git fetch
fatal: detected dubious ownership in repository at '/home/justin/work/ignition_projects'
To add an exception for this directory, call:

        git config --global --add safe.directory /home/justin/work/ignition_projects

```

Probably simplest to run the image on my devstation as root and pass in my UID/GID ... 😕

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [March 27, 2023, 7:39pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/9 "2023-03-27T19:39:36Z")

</div>

> [@justin.brzozoski](#):
>
> Probably simplest to run the image on my devstation as root and pass in my UID/GID ... 😕

Also agreed. If you use the `IGNITION_UID` and `IGNITION_GID` environment variables combined with starting the gateway as `root`, it should work fine (and Ignition itself will still end up running as that desired `IGNITION_UID` through the root stepdown). Only other path would be to reset file ownership of the Ignition installation within your derived image to your target UID/GID; only trouble there is if you've got other users whose workstations have different UID/GIDs (likely). That is why we've retained that root stepdown functionality--for dev.

---

<div class="post-metadata">

**Author:** ![Brian\_Claeys](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian\_Claeys](https://forum.inductiveautomation.com/u/Brian_Claeys)\
**Post date:** [May 29, 2024, 6:40pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/10 "2024-05-29T18:40:31Z")

</div>

I was upgrading from version 8.1.1 to 8.1.39, and I ran into this issue. Adding "user: 0:0", "IGNITION\_UID: 2003" and "IGNITION\_GID: 2003" to my docker compose file fixed the Permission denied error, but when I removed those lines from the config the error presented itself again. It worked again when I re-added those to the config, but it was not the expected result. I feel like I still may be missing something to complete the upgrade. Any thoughts on this?

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [May 29, 2024, 6:49pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/11 "2024-05-29T18:49:56Z")

</div>

What do you have in the container logs when you try to launch after removing the run-as-root and the `IGNITION_UID`/`IGNITION_GID` environment variables? It might help to see the exact error[s].

When you launch as `root` (i.e. uid:gid `0:0`), and you've specified the `IGNITION_UID` and `IGNITION_GID` vars, you should see something to the effect of:

```python
init | 2024/05/29 13:48:47 | Adjusting ownership of 487 Ignition installation files to uid=2003,gid=2003.

```

... indicating that the entrypoint (as root) has updated the permissions of those files to match the target user/group.

EDIT: I did a quick sanity check w/ launching our old `8.1.1` image and upgrading [to 8.1.41] as described above and everything worked as expected.

---

<div class="post-metadata">

**Author:** ![Brian\_Claeys](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian\_Claeys](https://forum.inductiveautomation.com/u/Brian_Claeys)\
**Post date:** [June 3, 2024, 7:16pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/12 "2024-06-03T19:16:25Z")

</div>

Here are the logs when it is run with `IGNITION_UID=2003` and `IGNITION_GID=2003` and user: 0:0. This is not from the time that the image was upgraded, and I may not have access to the logs from when it was upgraded until I can upgrade another instance in a couple of weeks.

init | 2024/05/29 11:39:50 | Parsed systemName argument; new value: ignition-gateway  
init | 2024/05/29 11:39:50 | Parsed maxMemory argument; new value: 4096  
init | 2024/05/29 11:39:50 | Creating init.properties file  
init | 2024/05/29 11:39:50 | Adding SystemName=ignition-gateway to init.properties  
init | 2024/05/29 11:39:50 | Starting Ignition gateway  
e]0;Ignition GatewayaYinit | 2024/06/02 06:29:31 | Parsed systemName argument; new value: ignition-gateway  
init | 2024/06/02 06:29:31 | Parsed maxMemory argument; new value: 4096  
init | 2024/06/02 06:29:31 | Creating init.properties file  
init | 2024/06/02 06:29:31 | Adding SystemName=ignition-gateway to init.properties  
init | 2024/06/02 06:29:31 | Starting Ignition gateway

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [June 3, 2024, 7:55pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/13 "2024-06-03T19:55:40Z")

</div>

I'd double check whether you've successfully applied those environment variables. One way to check would be to inspect the currently running container, e.g. (⚠ make sure you don't post this output if you've got sensitive values in the environment):

 ![SCR-20240603-nfaf](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/5/b502d63e0338cc35d01ccc586fa8895a07db6e54.png)

If those environment variables are applied and you've launched the container as root, then you should see something like this at the beginning of the logs:

```python
...
init | 2024/06/03 19:46:37 | Adjusting ownership of 487 Ignition installation files to uid=2003,gid=2003.
init | 2024/06/03 19:46:37 | Staging user step-down from root to uid=2003,gid=2003
...

```

Are there any other particulars of this environment that you can share? Is this just running on a typical flavor of Linux with Docker Engine?

---

<div class="post-metadata">

**Author:** ![e4andVibes](https://avatars.discourse-cdn.com/v4/letter/e/51bf81/32.png) [@e4andVibes](https://forum.inductiveautomation.com/u/e4andVibes)\
**Post date:** [July 13, 2026, 11:18am UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/14 "2026-07-13T11:18:08Z")

</div>

Just out of curiosity, will the below approach work for new installations of version 8.1.26+ on Linux?

- Create service user (no login), and service group
- Add the directories from host which will be volume mounted to be owned by service user
- Add bind mounted directories or files to have read access by service user
- pass service user and group ID via ignition environment variables in the compose.yml file

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [July 13, 2026, 1:52pm UTC](https://forum.inductiveautomation.com/t/docker-image-now-defaults-to-non-root-user/69784/15 "2026-07-13T13:52:18Z")

</div>

If you create your service user/group with UID/GID of 2003, then you won't have to use root stepdown and the env vars to have the bind-mounts be R/W by the in-container `ignition` user.
