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 /data
just 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
\n
and not\r\n
- I have tried switching between shell and exec forms for the
ENTRYPOINT
directive
System Information
I am running on a fresh Ubuntu 24 instance with a standard Docker installation.