factoriotools / factorio-docker

Factorio headless server in a Docker container
https://hub.docker.com/r/factoriotools/factorio/
MIT License
1.09k stars 245 forks source link

Unable to run with Rootless Docker configuration. #496

Open ScidaJ opened 4 months ago

ScidaJ commented 4 months ago

Hello, I have a little server box running NixOS, and I'm trying to launch the container to complete the setup, however the container fails to launch with the error chown: changing ownership of '/factorio': Operation not permitted The line that fails is chown -R factorio:factorio /factorio

I have followed all of the setup instructions as best I could, but solving this issue has eluded me.

I launch the container using docker-compose up -d, as my Docker is configured Rootless as is described in the NixOS and Docker documentation.

Any help is appreciated.

gabevenberg commented 1 month ago

Could you share your relevant nix config snippets?

ScidaJ commented 1 month ago

Hi, this is my Docker config in my configuration.nix file.

# Virtualisation Configuration
  virtualisation.docker.rootless = {
    enable = true;
    setSocketVariable = true;
  };

I have an existing save that I was looking to transfer over but that was something to be done after the server was up and running on that machine, so I was using the example Docker Compose configuration in the README for the Factorio server.

version: '2'
services:
  factorio:
    image: factoriotools/factorio
    ports:
     - "34197:34197/udp"
     - "27015:27015/tcp"
    volumes:
     - /opt/factorio:/factorio

If you need any other information please let me know, thank you.

oskarkaczmarek commented 1 month ago

Have you chown'ed the right directory? I will personally set it up myself later today, but according to the example setup the data is stored in /opt/factorio.

ScidaJ commented 1 month ago

I believe I did but it has been a while since I tried to launch it, I'll give it another go. Yup, it fails with the error that I gave in the issue. I have done all of the setup steps. Here's the log from the container

+ FACTORIO_VOL=/factorio
+ LOAD_LATEST_SAVE=true
+ GENERATE_NEW_SAVE=true
+ PRESET=
+ SAVE_NAME=
+ BIND=
+ CONSOLE_LOG_LOCATION=
+ mkdir -p /factorio
+ mkdir -p /factorio/saves
+ mkdir -p /factorio/config
+ mkdir -p /factorio/mods
+ mkdir -p /factorio/scenarios
+ mkdir -p /factorio/script-output
+ [[ ! -f /factorio/config/rconpw ]]
+ [[ ! -f /factorio/config/server-settings.json ]]
+ [[ ! -f /factorio/config/map-gen-settings.json ]]
+ [[ ! -f /factorio/config/map-settings.json ]]
++ find -L /factorio/saves -iname '*.tmp.zip' -mindepth 1
++ wc -l
+ NRTMPSAVES=0
+ [[ 0 -gt 0 ]]
+ [[ true == \t\r\u\e ]]
+ ./docker-update-mods.sh
+ EXEC=
++ id -u
+ [[ 0 = 0 ]]
+ usermod -o -u 845 factorio
usermod: no changes
+ groupmod -o -g 845 factorio
+ chown -R factorio:factorio /factorio
chown: changing ownership of '/factorio': Operation not permitted
Chronoes commented 1 month ago

The container expects the mounted folder to have UID:GID of 845:845. Rootless Docker is probably unable to change it if it's owned by a different user.

Can you check who the owner of /opt/factorio is on your host and try changing it to 845:845?

ScidaJ commented 1 month ago

Just double checked, chown'd to 845 using sudo chown -R 845:845 /opt/factorio, same error occurs when starting the container. I also tried doing sudo chmod g+w /opt/factorio just to make sure it had write permission too, seemingly no change.

Chronoes commented 1 month ago

After running some tests on my own in rootless Docker in Docker container (image docker:27.2-dind-rootless) I ran into the same issue with permissions.

My theory was that the rootless Docker daemon cannot change ownership of the mounted volume which is why this fails.

I don't know if there is a better solution to fix it in general but I chowned the /opt/factorio folder to my rootless Docker user (ID 1000) chown -R 1000:1000 /opt/factorio. Then starting the Factorio container worked and it chowned it to ID 100844, booting up the server.

Hope this helps.

ScidaJ commented 1 month ago

I must have done something wrong because I chown'd it to 1000:1000 using sudo chown -R 1000:1000 /opt/factorio and there was no change. This is the output of stat /opt/factorio after running the above command.

  File: /opt/factorio/
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: 259,2   Inode: 6291458     Links: 7
Access: (0775/drwxrwxr-x)  Uid: ( 1000/  jacobs)   Gid: ( 1000/ UNKNOWN)
Access: 2024-10-24 09:59:15.780897166 -0400
Modify: 2024-08-03 17:10:22.820413802 -0400
Change: 2024-10-24 09:59:07.273633759 -0400
 Birth: 2024-08-03 00:03:42.575882145 -0400
Chronoes commented 1 month ago

Did you start the Factorio server container afterwards?

ScidaJ commented 1 month ago

Yes, it still does not work but it tries to change ownership multiple times now instead of just once then failing.

ScidaJ commented 1 month ago

Took look at the ownership of some other directories that are being used by some other containers being ran, turns out my Docker uid is 100999 which did not show up when I listed the users, which was fun to find out. Changing ownership of /opt/factorio to 100999 using sudo chown -R 100999:100999 /opt/factorio fixed it, as @Chronoes suggested. Marking as closed as this issue seems to be fixed.

ScidaJ commented 4 days ago

So I'm reopening this as this issue isn't actually resolved. Because I am running Docker Rootless I cannot disable userland-proxy, which means that Docker's own proxy is still being used. The server starts up just fine, but it refuses to stay mapped to 34197, with the ping response changing the final server address as the ports inevitably don't match because of Docker's proxy. I've shared a screenshot of the container's logs on start up. That's the end of the log. I'm truly at a loss here with how to proceed with rootless Docker, and would really like to not use rootful Docker, so any help is appreciated. image

Edited to add: The port that the Docker proxy assigns is random every time, and I can't open every single port just in case the server decides that what it's running on today.