From 30281eaf06082a19b2360ad69aef56fc3dde742d Mon Sep 17 00:00:00 2001 From: John Skinner Date: Fri, 2 Aug 2024 15:36:04 -0500 Subject: [PATCH 1/4] added graceful exit, change GH Actions build process to buildx from buildah, make password not required --- .github/workflows/publish_image.yaml | 30 +++++++++--------- .github/workflows/publish_proton_image.yaml | 33 ++++++++++---------- README.md | 13 +++----- container/compose.yaml | 2 +- container/proton/entrypoint.sh | 25 ++++++++++----- container/wine/entrypoint.sh | 34 ++++++++++++++++++++- 6 files changed, 88 insertions(+), 49 deletions(-) diff --git a/.github/workflows/publish_image.yaml b/.github/workflows/publish_image.yaml index e705e53..1891931 100644 --- a/.github/workflows/publish_image.yaml +++ b/.github/workflows/publish_image.yaml @@ -1,4 +1,4 @@ -name: Build and push Docker image +name: Build and push Wine based image on: release: types: [published] @@ -6,21 +6,19 @@ jobs: build-push: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Build image - id: buildah - uses: redhat-actions/buildah-build@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 with: - image: enshrouded-dedicated-server - context: ./container/wine - containerfiles: ./container/wine/Dockerfile - tags: latest ${{ github.event.release.tag_name }} # Use latest and the release tag - - name: Push image to Docker Hub - uses: redhat-actions/push-to-registry@v2 - with: - image: ${{ steps.buildah.outputs.image }} - tags: ${{ steps.buildah.outputs.tags }} - registry: docker.io/${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: ./container/wine + file: Dockerfile + push: true + tags: + - ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:wine-latest + - ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:wine-${{ github.event.release.tag_name }} diff --git a/.github/workflows/publish_proton_image.yaml b/.github/workflows/publish_proton_image.yaml index 72b9b16..c0cd457 100644 --- a/.github/workflows/publish_proton_image.yaml +++ b/.github/workflows/publish_proton_image.yaml @@ -1,24 +1,25 @@ name: Build and push GE-Proton based image -on: workflow_dispatch +on: + release: + types: [published] jobs: build-push: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Build image - id: buildah - uses: redhat-actions/buildah-build@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 with: - image: enshrouded-dedicated-server - context: ./container/proton - containerfiles: ./container/proton/Dockerfile - tags: proton-latest - - name: Push image to Docker Hub - uses: redhat-actions/push-to-registry@v2 - with: - image: ${{ steps.buildah.outputs.image }} - tags: ${{ steps.buildah.outputs.tags }} - registry: docker.io/${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: ./container/proton + file: Dockerfile + push: true + tags: + - ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:latest + - ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:proton-latest + - ${{ secrets.DOCKERHUB_USERNAME }}/enshrouded-dedicated-server:proton-${{ github.event.release.tag_name }} diff --git a/README.md b/README.md index 333dc01..240aea7 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,10 @@ Run Enshrouded dedicated server in a container. Optionally includes helm chart f The processes within the container do **NOT** run as root. Everything runs as the user steam (gid:10000/uid:10000 by default). If you exec into the container, you will drop into `/home/steam` as the steam user. Enshrouded will be installed to `/home/steam/enshrouded`. Any persistent volumes should be mounted to `/home/steam/enshrouded/savegame` and be owned by 10000:10000. -In all of the examples below the image tag is set to `v2.0.5` which is the current latest release. I will update the examples each time I cut a new release. This is to avoid forcing potentially breaking changes if your tag is set to `latest` and you always pull. Please review my release notes for each version between your current and your target before upgrading. ### Proton and Wine based images -latest and semantic versioned (vN.N.N) image tags are Wine based images. If you would like to try my Proton (GE-Proton) based image, use the proton-latest tag. - -If testing shows that the Proton image is substantially more performant than the Wine image, I may retire the Wine image. +The `latest` tag is now based on the Proton build instead of Wine. This should be seamless. Outside of `latest`, there is `wine-$realease_version` and `proton-$release_version` with `$release_version` being the version of the release from GitHub. ### Ports @@ -55,7 +52,7 @@ docker run \ --env=SERVER_PASSWORD='ChangeThisPlease' \ --env=GAME_PORT=15636 \ --env=QUERY_PORT=15637 \ - sknnr/enshrouded-dedicated-server:v2.0.5 + sknnr/enshrouded-dedicated-server:latest ``` ### Docker Compose @@ -76,7 +73,7 @@ compose.yaml file: ```yaml services: enshrouded: - image: sknnr/enshrouded-dedicated-server:v2.0.5 + image: sknnr/enshrouded-dedicated-server:latest ports: - "15636:15636/udp" - "15637:15637/udp" @@ -112,7 +109,7 @@ podman run \ --env=SERVER_PASSWORD='ChangeThisPlease' \ --env=GAME_PORT=15636 \ --env=QUERY_PORT=15637 \ - docker.io/sknnr/enshrouded-dedicated-server:v2.0.5 + docker.io/sknnr/enshrouded-dedicated-server:latest ``` ### Quadlet @@ -122,7 +119,7 @@ To run the container with Podman's new quadlet subsystem, make a file under (whe Description=Enshrouded Game Server [Container] -Image=docker.io/sknnr/enshrouded-dedicated-server:v2.0.5 +Image=docker.io/sknnr/enshrouded-dedicated-server:latest Volume=enshrouded-persistent-data:/home/steam/enshrouded/savegame PublishPort=15636-15637:15636-15637/udp ContainerName=enshrouded-server diff --git a/container/compose.yaml b/container/compose.yaml index 47b00d5..a7e927b 100644 --- a/container/compose.yaml +++ b/container/compose.yaml @@ -1,6 +1,6 @@ services: enshrouded: - image: sknnr/enshrouded-dedicated-server:v2.0.4 + image: sknnr/enshrouded-dedicated-server:latest ports: - "15636:15636/udp" - "15637:15637/udp" diff --git a/container/proton/entrypoint.sh b/container/proton/entrypoint.sh index 42a19f8..db3dd22 100755 --- a/container/proton/entrypoint.sh +++ b/container/proton/entrypoint.sh @@ -5,6 +5,12 @@ timestamp () { date +"%Y-%m-%d %H:%M:%S,%3N" } +shutdown () { + echo "" + echo "$(timestamp) INFO: Recieved SIGTERM, shutting down gracefully" + kill -2 $enshrouded_pid +} + # Validate arguments if [ -z "$SERVER_NAME" ]; then SERVER_NAME='Enshrouded Containerized' @@ -12,8 +18,7 @@ if [ -z "$SERVER_NAME" ]; then fi if [ -z "$SERVER_PASSWORD" ]; then - echo "$(timestamp) ERROR: SERVER_PASSWORD not set, exitting" - exit 1 + echo "$(timestamp) WARN: SERVER_PASSWORD not set, server will be open to the public" fi if [ -z "$GAME_PORT" ]; then @@ -68,7 +73,9 @@ rm "${ENSHROUDED_PATH}/savegame/test" echo "$(timestamp) INFO: Updating Enshrouded Server configuration" tmpfile=$(mktemp) jq --arg n "$SERVER_NAME" '.name = $n' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG -jq --arg p "$SERVER_PASSWORD" '.password = $p' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG +if [ -z "$SERVER_PASSWORD" ]; then + jq --arg p "$SERVER_PASSWORD" '.password = $p' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG +fi jq --arg g "$GAME_PORT" '.gamePort = ($g | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG jq --arg q "$QUERY_PORT" '.queryPort = ($q | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG jq --arg s "$SERVER_SLOTS" '.slotCount = ($s | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG @@ -110,9 +117,13 @@ while [ $timeout -lt 11 ]; do echo "$(timestamp) INFO: Waiting for enshrouded_server.exe to be running" done -# I don't love this but I can't use `wait` because it's not a child of our shell +# Hold us open until we recieve a SIGTERM +wait $enshrouded_pid + +# Handle post SIGTERM from here +# Hold us open until WSServer-Linux pid closes, indicating full shutdown, then go home tail --pid=$enshrouded_pid -f /dev/null -# If we lose our pid, exit container -echo "$(timestamp) ERROR: He's dead, Jim" -exit 1 +# o7 +echo "$(timestamp) INFO: Shutdown complete." +exit 0 diff --git a/container/wine/entrypoint.sh b/container/wine/entrypoint.sh index d487815..8ea7b57 100755 --- a/container/wine/entrypoint.sh +++ b/container/wine/entrypoint.sh @@ -5,6 +5,12 @@ timestamp () { date +"%Y-%m-%d %H:%M:%S,%3N" } +shutdown () { + echo "" + echo "$(timestamp) INFO: Recieved SIGTERM, shutting down gracefully" + kill -2 $enshrouded_pid +} + # Validate arguments if [ -z "$SERVER_NAME" ]; then SERVER_NAME='Enshrouded Containerized' @@ -79,4 +85,30 @@ export WINEDEBUG=-all # Launch Enshrouded echo "$(timestamp) INFO: Starting Enshrouded Dedicated Server" -wine ${ENSHROUDED_PATH}/enshrouded_server.exe +wine ${ENSHROUDED_PATH}/enshrouded_server.exe & + +# Find pid for enshrouded_server.exe +timeout=0 +while [ $timeout -lt 11 ]; do + if ps -e | grep "enshrouded_serv"; then + enshrouded_pid=$(ps -e | grep "enshrouded_serv" | awk '{print $1}') + break + elif [ $timeout -eq 10 ]; then + echo "$(timestamp) ERROR: Timed out waiting for enshrouded_server.exe to be running" + exit 1 + fi + sleep 6 + ((timeout++)) + echo "$(timestamp) INFO: Waiting for enshrouded_server.exe to be running" +done + +# Hold us open until we recieve a SIGTERM +wait $enshrouded_pid + +# Handle post SIGTERM from here +# Hold us open until WSServer-Linux pid closes, indicating full shutdown, then go home +tail --pid=$enshrouded_pid -f /dev/null + +# o7 +echo "$(timestamp) INFO: Shutdown complete." +exit 0 From 72a337492e3c4d49d71a4e86aded59f9b760455e Mon Sep 17 00:00:00 2001 From: John Skinner Date: Fri, 2 Aug 2024 15:38:10 -0500 Subject: [PATCH 2/4] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 240aea7..466bc07 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The `latest` tag is now based on the Proton build instead of Wine. This should b | Name | Description | Default | Required | | ---- | ----------- | ------- | -------- | | SERVER_NAME | Name for the Server | Enshrouded Containerized | False | -| SERVER_PASSWORD | Password for the server | None | True | +| SERVER_PASSWORD | Password for the server | None | False | | GAME_PORT | Port for server connections | 15636 | False | | QUERY_PORT | Port for steam query of server | 15637 | False | | SERVER_SLOTS | Number of slots for connections (Max 16) | 16 | False | From 1989e694b5be3c9f4ea047380f6fec292a1e7d8d Mon Sep 17 00:00:00 2001 From: John Skinner Date: Fri, 2 Aug 2024 16:39:16 -0500 Subject: [PATCH 3/4] add trap for sigterm --- container/proton/entrypoint.sh | 5 ++++- container/wine/Dockerfile | 1 + container/wine/entrypoint.sh | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/container/proton/entrypoint.sh b/container/proton/entrypoint.sh index dafe731..7eab434 100755 --- a/container/proton/entrypoint.sh +++ b/container/proton/entrypoint.sh @@ -11,6 +11,9 @@ shutdown () { kill -2 $enshrouded_pid } +# Set our trap +trap 'shutdown' TERM + # Validate arguments if [ -z "$SERVER_NAME" ]; then SERVER_NAME='Enshrouded Containerized' @@ -118,7 +121,7 @@ while [ $timeout -lt 11 ]; do done # Hold us open until we recieve a SIGTERM -wait $enshrouded_pid +wait # Handle post SIGTERM from here # Hold us open until WSServer-Linux pid closes, indicating full shutdown, then go home diff --git a/container/wine/Dockerfile b/container/wine/Dockerfile index 837737c..1becd3d 100644 --- a/container/wine/Dockerfile +++ b/container/wine/Dockerfile @@ -14,6 +14,7 @@ RUN groupadd -g $CONTAINER_GID steam \ && dpkg --add-architecture i386 \ && apt-get update \ && apt-get install --no-install-recommends -y \ + procps \ ca-certificates \ curl \ wget \ diff --git a/container/wine/entrypoint.sh b/container/wine/entrypoint.sh index 5bb092d..022b38f 100755 --- a/container/wine/entrypoint.sh +++ b/container/wine/entrypoint.sh @@ -11,6 +11,9 @@ shutdown () { kill -2 $enshrouded_pid } +# Set our trap +trap 'shutdown' TERM + # Validate arguments if [ -z "$SERVER_NAME" ]; then SERVER_NAME='Enshrouded Containerized' @@ -103,7 +106,7 @@ while [ $timeout -lt 11 ]; do done # Hold us open until we recieve a SIGTERM -wait $enshrouded_pid +wait # Handle post SIGTERM from here # Hold us open until WSServer-Linux pid closes, indicating full shutdown, then go home From 7e077b6268bb2a5740029e58d9daad8813d484c5 Mon Sep 17 00:00:00 2001 From: John Skinner Date: Fri, 2 Aug 2024 17:41:07 -0500 Subject: [PATCH 4/4] modify wine dockerfile for no password --- container/proton/entrypoint.sh | 2 +- container/wine/entrypoint.sh | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/container/proton/entrypoint.sh b/container/proton/entrypoint.sh index 7eab434..2bdc94d 100755 --- a/container/proton/entrypoint.sh +++ b/container/proton/entrypoint.sh @@ -85,7 +85,7 @@ jq --arg s "$SERVER_SLOTS" '.slotCount = ($s | tonumber)' ${ENSHROUDED_CONFIG} > jq --arg i "$SERVER_IP" '.ip = $i' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG # Wine talks too much and it's annoying -#export WINEDEBUG=-all +export WINEDEBUG=-all # Check that log directory exists, if not create if ! [ -d "${ENSHROUDED_PATH}/logs" ]; then diff --git a/container/wine/entrypoint.sh b/container/wine/entrypoint.sh index 022b38f..40fcabc 100755 --- a/container/wine/entrypoint.sh +++ b/container/wine/entrypoint.sh @@ -21,8 +21,7 @@ if [ -z "$SERVER_NAME" ]; then fi if [ -z "$SERVER_PASSWORD" ]; then - echo "$(timestamp) ERROR: SERVER_PASSWORD not set, exitting" - exit 1 + echo "$(timestamp) WARN: SERVER_PASSWORD not set, server will be open to the public" fi if [ -z "$GAME_PORT" ]; then @@ -77,7 +76,9 @@ rm "${ENSHROUDED_PATH}/savegame/test" echo "$(timestamp) INFO: Updating Enshrouded Server configuration" tmpfile=$(mktemp) jq --arg n "$SERVER_NAME" '.name = $n' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG -jq --arg p "$SERVER_PASSWORD" '.userGroups[].password = $p' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG +if [ -n "$SERVER_PASSWORD" ]; then + jq --arg p "$SERVER_PASSWORD" '.userGroups[].password = $p' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG +fi jq --arg g "$GAME_PORT" '.gamePort = ($g | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG jq --arg q "$QUERY_PORT" '.queryPort = ($q | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG jq --arg s "$SERVER_SLOTS" '.slotCount = ($s | tonumber)' ${ENSHROUDED_CONFIG} > "$tmpfile" && mv "$tmpfile" $ENSHROUDED_CONFIG