From 3adf75e632f565ff7baac1394c6193bfa87dccdd Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Wed, 14 Jun 2023 00:35:58 +0200 Subject: [PATCH] debian docker images using statically-linked binary (musl) debian 12.0 image variants: - docker pull joseluisq/static-web-server:2-debian - docker pull joseluisq/static-web-server:2.y-debian - docker pull joseluisq/static-web-server:2.y.z-debian --- .github/workflows/devel.docker.yml | 120 ++++++++++++++++++++++++++- .github/workflows/release.docker.yml | 53 ++++++++++++ .gitignore | 1 + Makefile | 9 ++ docker/debian/Dockerfile | 80 ++++++++++++++++++ docker/debian/entrypoint.sh | 10 +++ docker/devel/Dockerfile.debian | 37 +++++++++ docs/content/features/docker.md | 32 +++++-- 8 files changed, 333 insertions(+), 9 deletions(-) create mode 100644 docker/debian/Dockerfile create mode 100755 docker/debian/entrypoint.sh create mode 100644 docker/devel/Dockerfile.debian diff --git a/.github/workflows/devel.docker.yml b/.github/workflows/devel.docker.yml index 88c5af9d..30470c4f 100644 --- a/.github/workflows/devel.docker.yml +++ b/.github/workflows/devel.docker.yml @@ -14,7 +14,7 @@ env: jobs: docker-alpine: - name: Docker test + name: Docker test (alpine) strategy: matrix: arch: @@ -44,9 +44,9 @@ jobs: uses: actions/cache@v3 with: path: /tmp/.buildx-cache - key: static-web-server-${{ matrix.arch }}-buildx-${{ github.sha }} + key: static-web-server-${{ matrix.arch }}-alpine-buildx-${{ github.sha }} restore-keys: | - static-web-server-${{ matrix.arch }}-buildx- + static-web-server-${{ matrix.arch }}-alpine-buildx- - name: Set up QEMU uses: docker/setup-qemu-action@v2 @@ -125,3 +125,117 @@ jobs: run: | rm -rf /tmp/.buildx-cache mv /tmp/.buildx-cache-new /tmp/.buildx-cache + + docker-debian: + name: Docker test (debian) + strategy: + matrix: + arch: + - linux/amd64 + - linux/386 + - linux/arm64 + - linux/arm/v7 + - linux/arm/v6 + runs-on: ubuntu-22.04 + services: + registry: + image: registry:2 + ports: + - 5000:5000 + steps: + - + name: Dependencies + run: | + sudo apt-get install jq + - + name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 1 + - + name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: static-web-server-${{ matrix.arch }}-debian-buildx-${{ github.sha }} + restore-keys: | + static-web-server-${{ matrix.arch }}-debian-buildx- + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - + name: Docker meta debian + id: meta_debian + uses: docker/metadata-action@v4 + with: + images: ${{ env.DOCKER_IMAGE }} + flavor: | + latest=false + suffix=-debian + tags: | + type=schedule + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + driver-opts: network=host + - + name: Prepare Docker envs + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + scripts/ci/get_latest_release.sh + cat /tmp/version >> $GITHUB_ENV + cat /tmp/version + echo "SERVER_DOCKERFILE=./docker/debian/Dockerfile" >> $GITHUB_ENV + - + name: Build and export to Docker client + uses: docker/build-push-action@v4 + with: + context: . + platforms: ${{ matrix.arch }} + file: ${{ env.SERVER_DOCKERFILE }} + load: true + tags: ${{ steps.meta_debian.outputs.tags }} + labels: ${{ steps.meta_debian.outputs.labels }} + build-args: | + SERVER_VERSION=${{ env.SERVER_VERSION }} + - + name: Build and push to local registry + uses: docker/build-push-action@v4 + with: + context: . + platforms: ${{ matrix.arch }} + file: ${{ env.SERVER_DOCKERFILE }} + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta_debian.outputs.tags }} + labels: ${{ steps.meta_debian.outputs.labels }} + build-args: | + SERVER_VERSION=${{ env.SERVER_VERSION }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + - + name: Inspect image + run: | + docker image inspect ${{ env.DOCKER_IMAGE }}:${{ steps.meta_debian.outputs.version }} + - + name: Check manifest + if: github.event_name != 'pull_request' + run: | + docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}:${{ steps.meta_debian.outputs.version }} + - + # Temp fix + # https://github.com/docker/build-push-action/issues/252 + # https://github.com/moby/buildkit/issues/1896 + name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache + diff --git a/.github/workflows/release.docker.yml b/.github/workflows/release.docker.yml index c15dd3af..b3ce8f5b 100644 --- a/.github/workflows/release.docker.yml +++ b/.github/workflows/release.docker.yml @@ -57,6 +57,59 @@ jobs: build-args: | SERVER_VERSION=${{ env.SERVER_VERSION }} + docker-image-debian: + needs: ['docker-image-alpine'] + runs-on: ubuntu-22.04 + if: contains(github.ref, 'v2.') + steps: + - + name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 1 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - + name: Docker meta debian + id: meta_debian + uses: docker/metadata-action@v4 + with: + images: joseluisq/static-web-server + flavor: | + latest=false + suffix=-debian + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Prepare Docker envs + shell: bash + run: | + echo "SERVER_VERSION=${GITHUB_REF##*/v}" >> $GITHUB_ENV + echo "SERVER_DOCKERFILE=./docker/debian/Dockerfile" >> $GITHUB_ENV + - + name: Build and push (debian) + uses: docker/build-push-action@v4 + with: + push: true + context: . + platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7,linux/arm/v6 + file: ${{ env.SERVER_DOCKERFILE }} + tags: ${{ steps.meta_debian.outputs.tags }} + build-args: | + SERVER_VERSION=${{ env.SERVER_VERSION }} + docker-image-scratch: needs: ['docker-image-alpine'] runs-on: ubuntu-22.04 diff --git a/.gitignore b/.gitignore index bc2d87ee..9278944b 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ docs/site docs/*/**.html */**/*.1 docs/docs +docker/devel/static-web-server !/docs !/tests/fixtures/**/* diff --git a/Makefile b/Makefile index 5e7b04c8..adfc0e9f 100644 --- a/Makefile +++ b/Makefile @@ -125,6 +125,15 @@ docker.image.alpine: -t joseluisq/${PKG_NAME}:devel-alpine . --pull=true .PHONY: docker.image.alpine +docker.image.debian: + @echo "Creating Docker Alpine image..." + @cp -frp ./target/x86_64-unknown-linux-gnu/release/static-web-server ./docker/devel/ + @docker build \ + --platform="linux/x86_64" \ + --rm=true -f ./docker/devel/Dockerfile.debian \ + -t joseluisq/${PKG_NAME}:devel-debian . --pull=true +.PHONY: docker.image.debian + ####################################### ########## Production tasks ########### diff --git a/docker/debian/Dockerfile b/docker/debian/Dockerfile new file mode 100644 index 00000000..932fc0df --- /dev/null +++ b/docker/debian/Dockerfile @@ -0,0 +1,80 @@ +FROM --platform=$BUILDPLATFORM debian:12.0-slim as build + +ARG TARGETPLATFORM +ARG SERVER_VERSION=0.0.0 +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 \ + && true + +RUN set -ex \ + && case "$TARGETPLATFORM" in \ + "linux/amd64") target='x86_64-unknown-linux-musl' ;; \ + "linux/arm64") target='aarch64-unknown-linux-musl' ;; \ + "linux/386") target='i686-unknown-linux-musl' ;; \ + "linux/arm/v7") target='armv7-unknown-linux-musleabihf' ;; \ + "linux/arm/v6") target='arm-unknown-linux-musleabihf' ;; \ + *) echo >&2 "error: unsupported $TARGETPLATFORM architecture"; exit 1 ;; \ + esac \ + && curl -Lo /tmp/static-web-server.tar.gz \ + "https://github.com/static-web-server/static-web-server/releases/download/v${SERVER_VERSION}/static-web-server-v${SERVER_VERSION}-${target}.tar.gz" \ + && tar xzvf /tmp/static-web-server.tar.gz \ + && cp static-web-server-v${SERVER_VERSION}-${target}/static-web-server /usr/local/bin/ \ + && rm -rf /tmp/static-web-server.tar.gz static-web-server-v${SERVER_VERSION}-${target} \ + && chmod +x /usr/local/bin/static-web-server \ + && true + +RUN set -ex \ + && echo "Testing Docker image..." \ + && uname -a \ + && cat /etc/os-release \ + && echo VERSION_NUMBER=$(cat /etc/debian_version) \ + && static-web-server --version \ + && static-web-server --help \ + && file /usr/local/bin/static-web-server \ + && true + +FROM debian:12.0-slim + +ARG SERVER_VERSION=0.0.0 +ENV SERVER_VERSION=${SERVER_VERSION} + +LABEL version="${SERVER_VERSION}" \ + description="A cross-platform, high-performance and asynchronous web server for static files-serving." \ + maintainer="Jose Quintana " + +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 \ + # 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 + +EXPOSE 80 + +STOPSIGNAL SIGQUIT + +ENTRYPOINT ["/entrypoint.sh"] + +CMD ["static-web-server"] + +# Metadata +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://static-web-server.net" diff --git a/docker/debian/entrypoint.sh b/docker/debian/entrypoint.sh new file mode 100755 index 00000000..71caeafb --- /dev/null +++ b/docker/debian/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -e + +# Check if incoming command contains flags. +if [ "${1#-}" != "$1" ]; then + set -- static-web-server "$@" +fi + +exec "$@" diff --git a/docker/devel/Dockerfile.debian b/docker/devel/Dockerfile.debian new file mode 100644 index 00000000..cf327e0a --- /dev/null +++ b/docker/devel/Dockerfile.debian @@ -0,0 +1,37 @@ +FROM debian:12.0-slim + +ENV SERVER_VERSION=devel + +LABEL version="${SERVER_VERSION}" \ + description="A cross-platform, high-performance and asynchronous web server for static files-serving." \ + maintainer="Jose Quintana " + +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 \ + # 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 + +EXPOSE 80 + +STOPSIGNAL SIGQUIT + +ENTRYPOINT ["/entrypoint.sh"] + +CMD ["static-web-server"] + +# Metadata +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" diff --git a/docs/content/features/docker.md b/docs/content/features/docker.md index 43446151..96ba3ac5 100644 --- a/docs/content/features/docker.md +++ b/docs/content/features/docker.md @@ -1,10 +1,12 @@ # Docker -`SWS` has first-class [Docker](https://docs.docker.com/get-started/overview/) support. It provides a [Scratch](https://hub.docker.com/_/scratch) as well as the latest [Alpine Linux](https://hub.docker.com/_/alpine) Docker images. +`SWS` has first-class [Docker](https://docs.docker.com/get-started/overview/) support. + +It is provided in three Docker image variants such as [Scratch](https://hub.docker.com/_/scratch), [Alpine](https://hub.docker.com/_/alpine) and [Debian](https://hub.docker.com/_/debian) images. ## OS/Arch -Only the following operating systems and architectures are supported. +All Docker images are [Multi-Arch](https://www.docker.com/blog/how-to-rapidly-build-multi-architecture-images-with-buildx/) and the following operating systems and architectures are supported. - `linux/386` - `linux/amd64` @@ -12,6 +14,9 @@ Only the following operating systems and architectures are supported. - `linux/arm/v7` - `linux/arm64` +!!! 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/). + View all images on [Docker Hub](https://hub.docker.com/r/joseluisq/static-web-server/). ## Run a container @@ -22,36 +27,51 @@ To give the server a quick try then just run the following commands. - [The SWS CLI arguments](/configuration/command-line-arguments/) can be provided directly to the container or omitted as shown below. - A Docker volume like `-v $HOME/my-public-dir:/public` can be specified to overwrite the default root directory. -Run the scratch Docker image (just the binary) +To run SWS, there are several Docker image variants that you can use. + +**Scratch** image variant (just the binary) ```sh docker run --rm -it -p 8787:80 joseluisq/static-web-server:2 -g info ``` -Or run the Alpine Docker image variant +**Alpine** Docker image variant ```sh docker run --rm -it -p 8787:80 joseluisq/static-web-server:2-alpine -g info ``` +**Debian** Docker image variant + +```sh +docker run --rm -it -p 8787:80 joseluisq/static-web-server:2-debian -g info +``` + ## Dockerfile SWS Docker images can be extended as needed. -Extending the scratch Docker image (just the binary) +Extending the **Scratch** Docker image (just the binary) ```Dockerfile FROM joseluisq/static-web-server:2 # do stuff... ``` -Or the Alpine Docker image variant +Or the **Alpine** Docker image variant ```Dockerfile FROM joseluisq/static-web-server:2-alpine # do stuff... ``` +Or the **Debian** Docker image variant + +```Dockerfile +FROM joseluisq/static-web-server:2-debian +# do stuff... +``` + ## Docker Compose Below a [Docker Compose](https://docs.docker.com/compose/) example using the [Traefik Proxy](https://traefik.io/traefik/).