diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 07de5530..fd485151 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -14,11 +14,23 @@ jobs: permissions: contents: read packages: write + strategy: + matrix: + service: + - name: GameServer + dockerfile: Dockerfile + container_id: refresh + - name: HttpsProxy + dockerfile: HttpsProxy.Dockerfile + container_id: refresh-httpsproxy + - name: PresenceServer + dockerfile: PresenceServer.Dockerfile + container_id: refresh-presenceserver steps: - name: Checkout repository uses: actions/checkout@v4 - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + uses: docker/login-action@v3.3.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -26,15 +38,16 @@ jobs: # This step below will fill in things like name, description, etc. from the repository. # It's helpful for us because it also fills in the version information automatically depending on how the job was invoked. # See https://github.com/docker/metadata-action#basic - - name: Extract metadata (tags, labels) for Docker + - name: Extract metadata for ${{ matrix.service.name }} id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + uses: docker/metadata-action@v5.5.1 with: - images: ghcr.io/littlebigrefresh/refresh - - name: Build and push Docker image - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + images: ghcr.io/${{ github.repository_owner }}/${{ matrix.service.container_id }} + - name: Build and push ${{ matrix.service.name }} + uses: docker/build-push-action@v6.7.0 with: context: . + file: ${{ matrix.service.dockerfile }} push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index a78e360e..da9fce76 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build stage -FROM mcr.microsoft.com/dotnet/sdk:8.0.203-bookworm-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0.401-1-bookworm-slim AS build WORKDIR /build COPY *.sln ./ @@ -19,7 +19,7 @@ RUN dotnet publish Refresh.GameServer -c Release --property:OutputPath=/build/pu # Final running container -FROM mcr.microsoft.com/dotnet/runtime:8.0.3-bookworm-slim AS final +FROM mcr.microsoft.com/dotnet/runtime:8.0.8-bookworm-slim AS final # Add non-root user RUN set -eux && \ @@ -36,6 +36,9 @@ COPY --from=build /build/publish/publish /refresh/app COPY --from=build /build/scripts/docker-entrypoint.sh /refresh RUN chown -R refresh:refresh /refresh && \ -chmod +x /refresh/docker-entrypoint.sh +chmod +x /refresh/docker-entrypoint.sh -ENTRYPOINT ["/refresh/docker-entrypoint.sh"] +ENV PRIV_CMD gosu +ENV PRIV_USER refresh + +ENTRYPOINT ["/refresh/docker-entrypoint.sh", "GameServer"] diff --git a/HttpsProxy.Dockerfile b/HttpsProxy.Dockerfile new file mode 100644 index 00000000..397dfc18 --- /dev/null +++ b/HttpsProxy.Dockerfile @@ -0,0 +1,42 @@ +# Build stage +FROM mcr.microsoft.com/dotnet/sdk:8.0.401-1-alpine3.20 AS build +WORKDIR /build + +COPY *.sln ./ +COPY **/*.csproj ./ + +RUN dotnet sln list | grep ".csproj" \ + | while read -r line; do \ + mkdir -p $(dirname $line); \ + mv $(basename $line) $(dirname $line); \ + done; + +RUN dotnet restore --use-current-runtime + +COPY . . + +RUN dotnet publish Refresh.HttpsProxy -c Release --property:OutputPath=/build/publish/ --no-restore --no-self-contained + +# Final running container + +FROM mcr.microsoft.com/dotnet/runtime:8.0.8-alpine3.20 AS final + +# Add non-root user +RUN set -eux && \ +apk add --no-cache su-exec && \ +su-exec nobody true && \ +addgroup -g 1001 refresh && \ +adduser -D -h /refresh -u 1001 -G refresh refresh && \ +mkdir -p /refresh/data && \ +mkdir -p /refresh/app + +COPY --from=build /build/publish/publish /refresh/app +COPY --from=build /build/scripts/docker-entrypoint.sh /refresh + +RUN chown -R refresh:refresh /refresh && \ +chmod +x /refresh/docker-entrypoint.sh + +ENV PRIV_CMD su-exec +ENV PRIV_USER refresh:refresh + +ENTRYPOINT ["/refresh/docker-entrypoint.sh", "HttpsProxy"] diff --git a/PresenceServer.Dockerfile b/PresenceServer.Dockerfile new file mode 100644 index 00000000..ea2edd6b --- /dev/null +++ b/PresenceServer.Dockerfile @@ -0,0 +1,42 @@ +# Build stage +FROM mcr.microsoft.com/dotnet/sdk:8.0.401-1-alpine3.20 AS build +WORKDIR /build + +COPY *.sln ./ +COPY **/*.csproj ./ + +RUN dotnet sln list | grep ".csproj" \ + | while read -r line; do \ + mkdir -p $(dirname $line); \ + mv $(basename $line) $(dirname $line); \ + done; + +RUN dotnet restore --use-current-runtime + +COPY . . + +RUN dotnet publish Refresh.PresenceServer -c Release --property:OutputPath=/build/publish/ --no-restore --no-self-contained + +# Final running container + +FROM mcr.microsoft.com/dotnet/runtime:8.0.8-alpine3.20 AS final + +# Add non-root user +RUN set -eux && \ +apk add --no-cache su-exec && \ +su-exec nobody true && \ +addgroup -g 1001 refresh && \ +adduser -D -h /refresh -u 1001 -G refresh refresh && \ +mkdir -p /refresh/data && \ +mkdir -p /refresh/app + +COPY --from=build /build/publish/publish /refresh/app +COPY --from=build /build/scripts/docker-entrypoint.sh /refresh + +RUN chown -R refresh:refresh /refresh && \ +chmod +x /refresh/docker-entrypoint.sh + +ENV PRIV_CMD su-exec +ENV PRIV_USER refresh:refresh + +ENTRYPOINT ["/refresh/docker-entrypoint.sh", "PresenceServer"] diff --git a/docker-compose.yml b/docker-compose.yml index 4ef4fd73..4c6699ac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3' services: gameserver: image: refresh:latest @@ -16,4 +15,33 @@ services: interval: 5s retries: 5 volumes: - - "./data:/refresh/data:z" + - "./data/gameserver:/refresh/data:z" + httpsproxy: + image: refresh-httpsproxy:latest + container_name: refresh-httpsproxy + build: + context: . + dockerfile: HttpsProxy.Dockerfile + restart: unless-stopped + ports: + - "10061:10061" + environment: + BUNKUM_DATA_FOLDER: /refresh/data + volumes: + - "./data/httpsproxy:/refresh/data:z" + profiles: ["optional-services"] + presenceserver: + image: refresh-presenceserver:latest + container_name: refresh-presenceserver + build: + context: . + dockerfile: PresenceServer.Dockerfile + restart: unless-stopped + ports: + - "10072:10072" + - "10061:10061" + environment: + BUNKUM_DATA_FOLDER: /refresh/data + volumes: + - "./data/presenceserver:/refresh/data:z" + profiles: ["optional-services"] diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index cdf39c5f..1b3f8614 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -4,8 +4,7 @@ # so it must be changed again during the entrypoint chown -R refresh:refresh /refresh/data -cd /refresh/data - -exec gosu refresh /refresh/app/Refresh.GameServer +cd /refresh/data || exit $? +exec $PRIV_CMD "$PRIV_USER" "/refresh/app/Refresh.$1" exit $? # Expose error code \ No newline at end of file