Skip to content

Commit 42a7bef

Browse files
authored
feat: migrate from Ubuntu to Alpine base image (#82)
BREAKING-CHANGE: migrating from Ubuntu to Alpine may cause incompatibilities with downstream OCI images based on it
1 parent 8dfe63f commit 42a7bef

File tree

10 files changed

+67
-44
lines changed

10 files changed

+67
-44
lines changed

.github/semantic-release/release.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
#!/usr/bin/env bash
1+
#!/usr/bin/env sh
22

3-
set -Eeuo pipefail
3+
set -eu
44

55
RELEASE_VERSION=$1
66
RELEASE_CHANNEL=${2:-'default'}
77

8-
if [[ -z "$ROOT_PROJECT_DIR" ]]; then
8+
if [ -z "$ROOT_PROJECT_DIR" ]; then
99
echo 'Error: environment variable "ROOT_PROJECT_DIR" is not set.'
1010
exit 1
1111
fi
@@ -17,7 +17,7 @@ export IMAGE_VERSION="$RELEASE_VERSION"
1717

1818
# The default channel binds to the default Git branch (i.e. "main")
1919
# If we release from "main" branch -> we add the "latest" tag
20-
IS_LATEST_RELEASE="$([ "$RELEASE_CHANNEL" == 'default' ] && echo 'true' || echo 'false')"
20+
IS_LATEST_RELEASE="$([ "$RELEASE_CHANNEL" = 'default' ] && echo 'true' || echo 'false')"
2121
export IS_LATEST_RELEASE
2222

2323
docker buildx bake release --print

.github/workflows/ci.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ jobs:
3232
# -> "objects.githubusercontent.com": Uploading of security reports
3333
# -> "raw.githubusercontent.com": Retrieve license file when building OCI image
3434
# -> "*.docker.io" & "*.docker.com": Standard interactions with Docker
35-
# -> "*.ubuntu.com": Standard interactions with Ubuntu APT repositories
35+
# -> "*.alpinelinux.org": Standard interactions with Alpine Linux package repositories
36+
# -> "cdn.fwupd.org": Firmware updates (Alpine)
3637
# -> "api.papermc.io": Dynamic retrieval of the PaperMC server
3738
# -> "mirror.gcr.io": Downloading of the Trivy security scanner
3839
# -> "piston-data.mojang.com": Downloading of the Mojang server
@@ -47,14 +48,12 @@ jobs:
4748
api.github.com:443
4849
objects.githubusercontent.com:443
4950
raw.githubusercontent.com:443
50-
index.docker.io:443
51-
registry-1.docker.io:443
52-
auth.docker.io:443
51+
*.docker.io:443
5352
production.cloudflare.docker.com:443
54-
archive.ubuntu.com:80
55-
security.ubuntu.com:80
56-
api.papermc.io:443
53+
dl-cdn.alpinelinux.org:443
54+
cdn.fwupd.org:443
5755
mirror.gcr.io:443
56+
api.papermc.io:443
5857
piston-data.mojang.com:443
5958
api.minecraftservices.com:443
6059

.github/workflows/release.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ jobs:
4545
# -> "objects.githubusercontent.com": Uploading of security reports
4646
# -> "raw.githubusercontent.com": Retrieve license file when building OCI image
4747
# -> "*.docker.io" & "*.docker.com": Standard interactions with Docker
48-
# -> "*.ubuntu.com": Standard interactions with Ubuntu APT repositories
48+
# -> "*.alpinelinux.org": Standard interactions with Alpine Linux package repositories
49+
# -> "cdn.fwupd.org": Firmware updates (Alpine)
4950
# -> "api.papermc.io": Dynamic retrieval of the PaperMC server
5051
# -> "mirror.gcr.io": Downloading of the Trivy security scanner
5152
# -> "api.nuget.org" & "registry.npmjs.org": Downloading semantic-release CLI
@@ -60,13 +61,10 @@ jobs:
6061
objects.githubusercontent.com:443
6162
raw.githubusercontent.com:443
6263
uploads.github.com:443
63-
index.docker.io:443
64-
registry-1.docker.io:443
65-
auth.docker.io:443
64+
*.docker.io:443
6665
production.cloudflare.docker.com:443
67-
archive.ubuntu.com:80
68-
security.ubuntu.com:80
69-
ports.ubuntu.com:80
66+
dl-cdn.alpinelinux.org:443
67+
cdn.fwupd.org:443
7068
api.papermc.io:443
7169
api.nuget.org:443
7270
registry.npmjs.org:443

README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ Dockerized and fine-grained customizable PaperMC server.
1313

1414
</div>
1515

16+
## Features
17+
18+
* Alpine-based image
19+
* Lightweight (~360 MB)
20+
* Multi-architecture support (amd64 & arm64)
21+
22+
TODO
23+
1624
## Contributing
1725

1826
If you want to help us improve the project, you can learn more about ways to do so [here](docs/CONTRIBUTING.md).
@@ -30,7 +38,13 @@ our [Security Policy](docs/SECURITY.md).
3038

3139
## Licence
3240

33-
This project is under the [GNU GPL v3.0](https://www.gnu.org/licenses/gpl-3.0.html) license.
41+
This project inherits its licensing from the included upstream projects. As such, it is licensed under
42+
the [GNU GPL v3.0](https://www.gnu.org/licenses/gpl-3.0.html) license, as it inherits from PaperMC, which in turn inherits it from the original Bukkit and
43+
CraftBukkit projects.
44+
45+
The distributed OCI image is based on [the Alpine one](https://hub.docker.com/_/alpine).
46+
As with all Docker images, these likely also contain other software which may be under other licenses. Details about Alpine packages can be
47+
found [here](https://pkgs.alpinelinux.org/packages).
3448

35-
As the distributed OCI image is based on [the Ubuntu one](https://hub.docker.com/_/ubuntu), additional licensing information can be
36-
found [here](https://ubuntu.com/legal/intellectual-property-policy).
49+
As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with
50+
any relevant licenses for all software contained within.

src/localdev.sh

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
#!/usr/bin/env bash
1+
#!/usr/bin/env sh
2+
# TODO: OWASP RULE#3 https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-3-limit-capabilities-grant-only-specific-capabilities-needed-by-a-container
3+
# TODO: OWASP RULE#4 https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-4-prevent-in-container-privilege-escalation
4+
# TODO: OWASP RULE#7 https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-7-limit-resources-memory-cpu-file-descriptors-processes-restarts
5+
# TODO: Same OWASP rules in test.sh file
6+
# TODO: document security recommendations adapted to this project
7+
# TODO: document requirements for OWASP RULE#8 https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-7-limit-resources-memory-cpu-file-descriptors-processes-restarts
8+
# TODO: try OWASP RULE#8 here
29

3-
set -Eeuo pipefail
10+
set -eu
411

5-
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)
12+
SCRIPT_DIR=$(cd "$(dirname "$0")" > /dev/null 2>&1 && pwd -P)
613

714
cd "${SCRIPT_DIR}/main/docker"
815

src/main/docker/Dockerfile

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
#
1717
# You should have received a copy of the GNU General Public License
1818
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19-
FROM docker.io/eclipse-temurin:21-jdk-noble@sha256:5d935f3e86b5b629fc8994503e89b73137b24048a5b465fbaa605de80c678b54 AS jre-build
19+
# TODO: migrate to Podman? https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#podman-as-an-alternative-to-docker
20+
FROM docker.io/eclipse-temurin:21-jdk-alpine@sha256:2f2f553ce09d25e2d2f0f521ab94cd73f70c9b21327a29149c23a2b63b8e29a0 AS jre-build
2021

2122
# Create a custom Java runtime
2223
#
@@ -29,11 +30,11 @@ RUN ${JAVA_HOME}/bin/jlink \
2930
--no-header-files \
3031
--output /jre
3132

32-
FROM docker.io/ubuntu:noble@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782 AS papermc-server-build
33+
FROM docker.io/alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c AS papermc-server-build
3334

3435
ARG MINECRAFT_VERSION
3536

36-
RUN if [[ -z "$MINECRAFT_VERSION" ]]; then \
37+
RUN if [ -z "$MINECRAFT_VERSION" ]; then \
3738
echo "Error: MINECRAFT_VERSION argument is not set." >&2; \
3839
exit 1; \
3940
fi
@@ -43,17 +44,14 @@ RUN echo "Building PaperMC server for Minecraft version: $MINECRAFT_VERSION"
4344
WORKDIR /build
4445

4546
# Install required dependencies
46-
RUN apt-get update && \
47-
apt-get upgrade -y && \
48-
apt-get install -y --no-install-recommends ca-certificates curl jq && \
49-
rm -rf /var/lib/apt/lists/*
47+
RUN apk add --no-cache ca-certificates curl jq
5048

5149
# Retrieve latest Paper server for the given version
5250
COPY --chmod=500 get-papermc-server.sh .
5351
RUN ./get-papermc-server.sh "$MINECRAFT_VERSION"
5452

55-
# TODO: what about an alpine variant?
56-
FROM docker.io/ubuntu:noble@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782
53+
# TODO: make the image UID/GID-agnostic (e.g., for compatibility with OpenShift)
54+
FROM docker.io/alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
5755

5856
# JRE setup
5957
ENV JAVA_HOME=/opt/java
@@ -65,17 +63,20 @@ COPY --from=jre-build /jre ${JAVA_HOME}
6563
ENV EULA=false
6664

6765
# Keep dependencies up-to-date
68-
# gettext is required for envsubst
69-
RUN apt-get update && \
70-
apt-get upgrade -y && \
71-
apt-get install -y --no-install-recommends gettext && \
72-
rm -rf /var/lib/apt/lists/*
66+
# bash is still required by start.sh for now (to be removed)
67+
# gettext is required for envsubst: https://pkgs.alpinelinux.org/package/edge/main/x86_64/gettext
68+
# libudev-zero is the Alpine-equivalent of libudev, which is required by PaperMC: https://pkgs.alpinelinux.org/package/edge/community/x86/libudev-zero
69+
RUN apk add --no-cache bash gettext libudev-zero
7370

7471
# Create the "papermc" user
75-
RUN groupadd --system papermc && useradd --system --gid papermc --create-home papermc
72+
#
73+
# Long-form parameters are not supported (e.g., --system, --group, --shell)
74+
# BusyBox "adduser" doc: https://busybox.net/downloads/BusyBox.html#adduser
75+
RUN addgroup -S papermc && adduser -S -G papermc -h /home/papermc -s /sbin/nologin papermc
7676

7777
# Lock root user for security purposes
78-
RUN passwd --lock root
78+
# TODO: remove since unecessary
79+
RUN passwd -l root
7980

8081
# Now rely exclusively on the PaperMC user (rootless mode)
8182
USER papermc

src/main/docker/docker-bake.hcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ target "dev" {
6767
]
6868
}
6969

70+
# TODO: OWASP RULE#13 https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-13-enhance-supply-chain-security
7071
target "release" {
7172
description = "Builds the image for production purposes."
7273
args = {

src/main/docker/get-papermc-server.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
#!/usr/bin/env bash
1+
#!/usr/bin/env sh
22
# Reference: https://docs.papermc.io/misc/downloads-api
33

4+
set -eu
5+
46
MINECRAFT_VERSION=$1
57

68
LATEST_BUILD=$(curl -sSf "https://api.papermc.io/v2/projects/paper/versions/${MINECRAFT_VERSION}/builds" | \

src/main/docker/runtime/start.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env bash
2+
# TODO: migrate to sh
23

34
set -Eeuo pipefail
45

src/test/docker/test.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#!/usr/bin/env bash
1+
#!/usr/bin/env sh
22
# Assumption: The OCI image is already built and tagged as 'djaytan/papermc-server:dev'
33

4-
set -Eeuo pipefail
4+
set -eu
55

66
CONTAINER_NAME='test-papermc-server'
77

@@ -33,7 +33,7 @@ while true; do
3333
ELAPSED_TIME=$((CURRENT_TIME - START_TIME))
3434

3535
# Check if timeout of 60 seconds has been reached
36-
if [[ $ELAPSED_TIME -gt 60 ]]; then
36+
if [ $ELAPSED_TIME -gt 60 ]; then
3737
echo "❌ Server failed to start within 60 seconds."
3838
exit 1
3939
fi

0 commit comments

Comments
 (0)