refactor: Rootless Debian and Alpine Docker images by default (#567)

* chore: setup user public directory, permissions and symlink
* chore: alpine and debian rootless
* docs: rootless information
This commit is contained in:
Jose Quintana
2025-11-17 23:22:20 +01:00
committed by GitHub
parent d48da4ca06
commit b23498458f
8 changed files with 188 additions and 44 deletions

View File

@@ -4,7 +4,12 @@ ARG TARGETPLATFORM
ARG SERVER_VERSION=0.0.0
ENV SERVER_VERSION=${SERVER_VERSION}
RUN apk --no-cache add ca-certificates tzdata file
RUN set -eux \
&& apk --no-cache add \
ca-certificates \
tzdata \
file \
&& true
RUN set -ex; \
case "$TARGETPLATFORM" in \
@@ -33,23 +38,55 @@ RUN set -ex \
FROM alpine:3.21.5
ARG SERVER_VERSION=0.0.0
ENV SERVER_VERSION=${SERVER_VERSION}
ARG SERVER_USER_NAME=sws
ARG SERVER_USER_ID=1000
ARG SERVER_GROUP_NAME=sws
ARG SERVER_GROUP_ID=1000
ENV SERVER_VERSION=$SERVER_VERSION
ENV SERVER_USER_ID=$SERVER_USER_ID
ENV SERVER_USER_NAME=$SERVER_USER_NAME
ENV SERVER_GROUP_ID=$SERVER_GROUP_ID
ENV SERVER_GROUP_NAME=$SERVER_GROUP_NAME
LABEL version="${SERVER_VERSION}" \
description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
maintainer="Jose Quintana <joseluisq.net>"
RUN apk --no-cache add ca-certificates tzdata
RUN set -eux \
&& addgroup -g $SERVER_GROUP_ID $SERVER_GROUP_NAME \
&& adduser -D -u $SERVER_USER_ID -G $SERVER_GROUP_NAME $SERVER_USER_NAME \
&& true
COPY --from=build /usr/local/bin/static-web-server /usr/local/bin/
COPY ./docker/alpine/entrypoint.sh /
COPY ./docker/public /public
RUN set -eux \
&& apk --no-cache add \
ca-certificates \
tzdata \
&& true
RUN set -eux \
&& mkdir -p /home/$SERVER_USER_NAME/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /home/$SERVER_USER_NAME \
&& ln -s /home/$SERVER_USER_NAME/public /var/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /var/public \
&& true
USER $SERVER_USER_NAME:$SERVER_GROUP_NAME
COPY --from=build --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
/usr/local/bin/static-web-server /usr/local/bin/static-web-server
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/alpine/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/public /home/$SERVER_USER_NAME/public
WORKDIR /home/$SERVER_USER_NAME
EXPOSE 80
STOPSIGNAL SIGQUIT
ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["static-web-server"]
@@ -59,4 +96,4 @@ LABEL org.opencontainers.image.vendor="Jose Quintana" \
org.opencontainers.image.title="Static Web Server" \
org.opencontainers.image.description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
org.opencontainers.image.version="${SERVER_VERSION}" \
org.opencontainers.image.documentation="https://github.com/static-web-server/static-web-server"
org.opencontainers.image.documentation="https://static-web-server.net"

View File

@@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM debian:12.12-slim AS build
FROM --platform=$BUILDPLATFORM debian:13.1-slim AS build
ARG TARGETPLATFORM
ARG SERVER_VERSION=0.0.0
@@ -7,10 +7,10 @@ ENV SERVER_VERSION=${SERVER_VERSION}
RUN set -eux \
&& DEBIAN_FRONTEND=noninteractive apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get install -qq -y --no-install-recommends --no-install-suggests \
ca-certificates \
curl \
file \
tzdata \
ca-certificates \
curl \
file \
tzdata \
&& true
RUN set -ex \
@@ -48,34 +48,62 @@ RUN set -ex \
&& file /usr/local/bin/static-web-server \
&& true
FROM debian:12.12-slim
FROM debian:13.1-slim
ARG SERVER_VERSION=0.0.0
ENV SERVER_VERSION=${SERVER_VERSION}
ARG SERVER_USER_NAME=sws
ARG SERVER_USER_ID=1000
ARG SERVER_GROUP_NAME=sws
ARG SERVER_GROUP_ID=1000
ENV SERVER_VERSION=$SERVER_VERSION
ENV SERVER_USER_ID=$SERVER_USER_ID
ENV SERVER_USER_NAME=$SERVER_USER_NAME
ENV SERVER_GROUP_ID=$SERVER_GROUP_ID
ENV SERVER_GROUP_NAME=$SERVER_GROUP_NAME
LABEL version="${SERVER_VERSION}" \
description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
maintainer="Jose Quintana <joseluisq.net>"
RUN set -eux \
&& groupadd -r -g $SERVER_GROUP_ID $SERVER_GROUP_NAME \
&& useradd -r -g $SERVER_GROUP_ID -u $SERVER_USER_ID $SERVER_USER_NAME \
&& true
RUN set -eux \
&& DEBIAN_FRONTEND=noninteractive apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get install -qq -y --no-install-recommends --no-install-suggests \
ca-certificates \
tzdata \
ca-certificates \
tzdata \
# Clean up local repository of retrieved packages and remove the package lists
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& true
COPY --from=build /usr/local/bin/static-web-server /usr/local/bin/
COPY ./docker/debian/entrypoint.sh /
COPY ./docker/public /public
RUN set -eux \
&& mkdir -p /home/$SERVER_USER_NAME/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /home/$SERVER_USER_NAME \
&& ln -s /home/$SERVER_USER_NAME/public /var/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /var/public \
&& true
USER $SERVER_USER_NAME:$SERVER_GROUP_NAME
COPY --from=build --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
/usr/local/bin/static-web-server /usr/local/bin/static-web-server
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/debian/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/public /home/$SERVER_USER_NAME/public
WORKDIR /home/$SERVER_USER_NAME
EXPOSE 80
STOPSIGNAL SIGQUIT
ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["static-web-server"]

View File

@@ -1,22 +1,55 @@
FROM alpine:3.21.5
ENV SERVER_VERSION=devel
ARG SERVER_VERSION=devel
ARG SERVER_USER_NAME=sws
ARG SERVER_USER_ID=1000
ARG SERVER_GROUP_NAME=sws
ARG SERVER_GROUP_ID=1000
ENV SERVER_VERSION=$SERVER_VERSION
ENV SERVER_USER_ID=$SERVER_USER_ID
ENV SERVER_USER_NAME=$SERVER_USER_NAME
ENV SERVER_GROUP_ID=$SERVER_GROUP_ID
ENV SERVER_GROUP_NAME=$SERVER_GROUP_NAME
LABEL version="${SERVER_VERSION}" \
description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
maintainer="Jose Quintana <joseluisq.net>"
RUN apk --no-cache add ca-certificates tzdata
RUN set -eux \
&& addgroup -g $SERVER_GROUP_ID $SERVER_GROUP_NAME \
&& adduser -D -u $SERVER_USER_ID -G $SERVER_GROUP_NAME $SERVER_USER_NAME \
&& true
COPY ./docker/devel/static-web-server /usr/local/bin/
COPY ./docker/alpine/entrypoint.sh /
COPY ./docker/public /public
RUN set -eux \
&& apk --no-cache add \
ca-certificates \
tzdata \
&& true
RUN set -eux \
&& mkdir -p /home/$SERVER_USER_NAME/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /home/$SERVER_USER_NAME \
&& ln -s /home/$SERVER_USER_NAME/public /var/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /var/public \
&& true
USER $SERVER_USER_NAME:$SERVER_GROUP_NAME
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/devel/static-web-server /usr/local/bin/static-web-server
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/debian/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/public /home/$SERVER_USER_NAME/public
WORKDIR /home/$SERVER_USER_NAME
EXPOSE 80
STOPSIGNAL SIGQUIT
ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["static-web-server"]
@@ -25,5 +58,5 @@ LABEL org.opencontainers.image.vendor="Jose Quintana" \
org.opencontainers.image.url="https://github.com/static-web-server/static-web-server" \
org.opencontainers.image.title="Static Web Server" \
org.opencontainers.image.description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
org.opencontainers.image.version="${SERVER_VERSION}" \
org.opencontainers.image.documentation="https://github.com/static-web-server/static-web-server"
org.opencontainers.image.version="$SERVER_VERSION" \
org.opencontainers.image.documentation="https://static-web-server.net"

View File

@@ -1,30 +1,59 @@
FROM debian:12.12-slim
FROM debian:13.1-slim
ENV SERVER_VERSION=devel
ARG SERVER_VERSION=devel
ARG SERVER_USER_NAME=sws
ARG SERVER_USER_ID=1000
ARG SERVER_GROUP_NAME=sws
ARG SERVER_GROUP_ID=1000
ENV SERVER_VERSION=$SERVER_VERSION
ENV SERVER_USER_ID=$SERVER_USER_ID
ENV SERVER_USER_NAME=$SERVER_USER_NAME
ENV SERVER_GROUP_ID=$SERVER_GROUP_ID
ENV SERVER_GROUP_NAME=$SERVER_GROUP_NAME
LABEL version="${SERVER_VERSION}" \
description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
maintainer="Jose Quintana <joseluisq.net>"
RUN set -eux \
&& groupadd -r -g $SERVER_GROUP_ID $SERVER_GROUP_NAME \
&& useradd -r -g $SERVER_GROUP_ID -u $SERVER_USER_ID $SERVER_USER_NAME \
&& true
RUN set -eux \
&& DEBIAN_FRONTEND=noninteractive apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get install -qq -y --no-install-recommends --no-install-suggests \
ca-certificates \
tzdata \
ca-certificates \
tzdata \
# Clean up local repository of retrieved packages and remove the package lists
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& true
COPY ./docker/devel/static-web-server /usr/local/bin/
COPY ./docker/debian/entrypoint.sh /
COPY ./docker/public /public
RUN set -eux \
&& mkdir -p /home/$SERVER_USER_NAME/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /home/$SERVER_USER_NAME \
&& ln -s /home/$SERVER_USER_NAME/public /var/public \
&& chown -R $SERVER_USER_NAME:$SERVER_GROUP_NAME /var/public \
&& true
USER $SERVER_USER_NAME:$SERVER_GROUP_NAME
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/devel/static-web-server /usr/local/bin/static-web-server
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/debian/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY --chown=$SERVER_USER_NAME:$SERVER_GROUP_NAME \
./docker/public /home/$SERVER_USER_NAME/public
WORKDIR /home/$SERVER_USER_NAME
EXPOSE 80
STOPSIGNAL SIGQUIT
ENTRYPOINT ["/entrypoint.sh"]
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["static-web-server"]
@@ -33,5 +62,5 @@ LABEL org.opencontainers.image.vendor="Jose Quintana" \
org.opencontainers.image.url="https://github.com/static-web-server/static-web-server" \
org.opencontainers.image.title="Static Web Server" \
org.opencontainers.image.description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
org.opencontainers.image.version="${SERVER_VERSION}" \
org.opencontainers.image.documentation="https://github.com/static-web-server/static-web-server"
org.opencontainers.image.version="$SERVER_VERSION" \
org.opencontainers.image.documentation="https://static-web-server.net"

View File

@@ -21,5 +21,5 @@ LABEL org.opencontainers.image.vendor="Jose Quintana" \
org.opencontainers.image.url="https://github.com/static-web-server/static-web-server" \
org.opencontainers.image.title="Static Web Server" \
org.opencontainers.image.description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
org.opencontainers.image.version="${SERVER_VERSION}" \
org.opencontainers.image.documentation="https://github.com/static-web-server/static-web-server"
org.opencontainers.image.version="$SERVER_VERSION" \
org.opencontainers.image.documentation="https://static-web-server.net"

View File

@@ -25,5 +25,5 @@ LABEL org.opencontainers.image.vendor="Jose Quintana" \
org.opencontainers.image.url="https://github.com/static-web-server/static-web-server" \
org.opencontainers.image.title="Static Web Server" \
org.opencontainers.image.description="A cross-platform, high-performance and asynchronous web server for static files-serving." \
org.opencontainers.image.version="${SERVER_VERSION}" \
org.opencontainers.image.documentation="https://github.com/static-web-server/static-web-server"
org.opencontainers.image.version="$SERVER_VERSION" \
org.opencontainers.image.documentation="https://static-web-server.net"

View File

@@ -21,6 +21,23 @@ All Docker images are [Multi-Arch](https://www.docker.com/blog/how-to-rapidly-bu
!!! tip "SWS statically-linked binary"
All the Docker images use the SWS statically-linked binary, meaning that the binary is highly optimized, performant, and dependency-free thanks to [musl libc](https://www.musl-libc.org/).
## Rootless
The **Debian** and **Alpine** Docker images are rootless **by default** using a dedicated `sws` user and group. This reduces the attack surface and improves security.
!!! info "Remember"
Users can still run the containers as root if they _explicitly_ set the user to _root_ when running the container, e.g., using the `--user root` flag with `docker run`.
The `static-web-server` binary and all files under `/home/sws` (home directory) are owned by the non-root `sws` user and group.
For convenience, those paths are also available:
- **Home directory:** `/home/sws`
- **Public directory:** `/home/sws/public`
- **Public directory symlink:** `/var/public` -> `/home/sws/public`
The current working directory is the _home directory_ by default.
## Run a container
To give the server a quick try just run the following commands.

View File

@@ -13,7 +13,7 @@ docker run --rm -it -p 8787:80 joseluisq/static-web-server:2
```
!!! info "Docker Tip"
You can specify a Docker volume like `-v $HOME/my-public-dir:/public` to overwrite the default root directory. See [Docker examples](features/docker.md).
You can specify a Docker volume like `-v $HOME/my-public-dir:/var/public` to overwrite the default root directory. See [Docker examples](features/docker.md).
- Type `static-web-server --help` or see the [Command-line arguments](./configuration/command-line-arguments.md) section.
- See how to configure the server using a [configuration file](configuration/config-file.md).