To preface, I am inexperienced with Docker, and I am struggling to resolve an issue after going through Docker’s documentation as well as combing through other forum posts. If this is an obvious problem to you, please understand that I didn’t come here without exhausting all other options I could think of.
Scenario
I am trying to containerize a GT: New Horizons server instance, which is logically a simple process:
- Download the server files
- Extract the files to a designated directory
- Create a volume for that directory that the host can manipulate as needed
- Run the start script provided by the server files as an entrypoint
Implementation
Dockerfile
To begin, I’ve written the following Dockerfile and stored it in a GitHub repository.
# Fetch GTNH Server & Extract
FROM alpine:latest as prepare
ARG GTNH_VERSION=2.6.1
ARG PORT=25565
WORKDIR /tmp
# Download Server
ADD https://downloads.gtnewhorizons.com/ServerPacks/GT_New_Horizons_${GTNH_VERSION}_Server_Java_17-21.zip gtnh.zip
# Extract Server Files
RUN unzip gtnh.zip -d gtnh && rm gtnh.zip
# Reconfigure Server Files
COPY --chmod=+x ["set_config.sh", "/tmp"]
RUN sh set_config.sh eula true gtnh/eula.txt # Agree to EULA
RUN sh set_config.sh server-port "${PORT}" gtnh/server.properties # Update Port
RUN sed -i '/^\s*java/!d' gtnh/startserver-java9.sh # Isolate Start Command
# Deploy Prepared Server
FROM ghcr.io/graalvm/jdk-community:21
COPY --from=prepare ["/tmp/gtnh", "/data"]
WORKDIR /data
VOLUME ["/data"]
EXPOSE ${PORT}
ENTRYPOINT exec sh startserver-java9.sh
To note, the GraalVM JDK instance does not come with an unzip command, so I opted to use a multi-stage build which prepares the server instance in an alpine container and then copies the prepared files into the graalvm container.
Compose File
Additionally, I have written the following Docker Compose file to build and run the instance:
services:
gtnh-server:
build:
context: '/home/user/gtnh-docker' # Contains the Dockerfile and additional scripts
dockerfile: 'Dockerfile'
args:
GTNH_VERSION: '2.6.1'
PORT: '25566'
volumes:
- './data:/data'
My intention is to bind the /data directory in the container which holds the server files to a directory on the host.
Issue
After pruning the system via sudo docker system prune -a, I navigate to the directory containing the compose file and run sudo docker compose up. The build steps execute successfully up until the entrypoint which produces the following error.
[+] Running 2/1
Network 261_default Created 0.0s
Container 261-gtnh-server-1 Created 0.0s
Attaching to gtnh-server-1
gtnh-server-1 | sh: startserver-java9.sh: No such file or directory
gtnh-server-1 exited with code 127
However, if I build an instance from the Dockerfile with context via docker build, and then run it via docker run, the script runs as expected.
Finally, after trying to start the instance from either docker run or the compose file, the host directory that’s mounted to the /data volume remains empty.
Attempts & Validation
- I ran a build with
RUN ls /datajust before the entrypoint to validate that the directory is populated; this printed out the server files as expected - I changed the file references from relative to absolute file paths and vice-versa with no luck
- I enforced that all new lines were encoded as
\nand not\r\n - I have tried switching between shell and exec forms for the
ENTRYPOINTdirective
System Information
I am running on a fresh Ubuntu 24 instance with a standard Docker installation.