Browse Source

feat: improve Docker images (#208)

Kévin Dunglas 1 year ago
parent
commit
22d4214529
5 changed files with 147 additions and 92 deletions
  1. 3 3
      .github/workflows/docker.yml
  2. 57 33
      Dockerfile
  3. 54 33
      alpine.Dockerfile
  4. 33 17
      caddy/frankenphp/Caddyfile
  5. 0 6
      docker-bake.hcl

+ 3 - 3
.github/workflows/docker.yml

@@ -37,7 +37,7 @@ jobs:
         env:
           LATEST: '1' # TODO: unset this variable when releasing the first tagged version
           SHA: ${{github.sha}}
-          VERSION: ${{github.ref_name}}
+          VERSION: ${{github.ref_type == 'tag' && github.ref_name || github.sha}}
 
   build:
     runs-on: ubuntu-latest
@@ -98,7 +98,7 @@ jobs:
         env:
           LATEST: '1' # TODO: unset this variable when releasing the first tagged version
           SHA: ${{github.sha}}
-          VERSION: ${{github.ref_name}}
+          VERSION: ${{github.ref_type == 'tag' && github.ref_name || github.sha}}
 
       # Workaround for https://github.com/actions/runner/pull/2477#issuecomment-1501003600
       - name: Export metadata
@@ -138,7 +138,7 @@ jobs:
         run: |
           docker run --platform=${{matrix.platform}} --rm \
             $(jq -r '."builder-${{matrix.variant}}"."containerimage.config.digest"' <<< $METADATA) \
-            "sh -c 'frankenphp version && go test ${{matrix.race}} -v ./... && cd caddy && go test ${{matrix.race}} -v ./...'"
+            sh -c 'go test ${{matrix.race}} -v ./... && cd caddy && go test ${{matrix.race}} -v ./...'
         env:
           METADATA: ${{steps.build.outputs.metadata}}
 

+ 57 - 33
Dockerfile

@@ -1,9 +1,51 @@
 # syntax=docker/dockerfile:1
-FROM php-base AS builder
+FROM php-base AS common
+
+WORKDIR /app
+
+RUN apt-get update && \
+    apt-get -y --no-install-recommends install \
+        mailcap \
+        libcap2-bin \
+    && \
+    apt-get clean
+
+RUN set -eux; \
+	mkdir -p \
+		/app/public \
+		/config/caddy \
+		/data/caddy \
+		/etc/caddy; \
+	sed -i 's/php/frankenphp run/g' /usr/local/bin/docker-php-entrypoint; \
+	echo '<?php phpinfo();' > /app/public/index.php
+
+COPY --link caddy/frankenphp/Caddyfile /etc/caddy/Caddyfile
+COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
+
+CMD ["--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
+HEALTHCHECK CMD curl -f https://localhost/healthz || exit 1
+
+# See https://caddyserver.com/docs/conventions#file-locations for details
+ENV XDG_CONFIG_HOME /config
+ENV XDG_DATA_HOME /data
+
+EXPOSE 80
+EXPOSE 443
+EXPOSE 443/udp
+EXPOSE 2019
+
+LABEL org.opencontainers.image.title=FrankenPHP
+LABEL org.opencontainers.image.description="The modern PHP app server"
+LABEL org.opencontainers.image.url=https://frankenphp.dev
+LABEL org.opencontainers.image.source=https://github.com/dunglas/frankenphp
+LABEL org.opencontainers.image.licenses=MIT
+LABEL org.opencontainers.image.vendor="Kévin Dunglas"
+
+
+FROM common AS builder
 
 ARG FRANKENPHP_VERSION='dev'
 
-COPY --from=golang-base /usr/local/go/bin/go /usr/local/go/bin/go
 COPY --from=golang-base /usr/local/go /usr/local/go
 
 ENV PATH /usr/local/go/bin:$PATH
@@ -25,53 +67,35 @@ RUN apt-get update && \
 
 WORKDIR /go/src/app
 
-COPY go.mod go.sum ./
+COPY --link go.mod go.sum ./
 RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
 
 RUN mkdir caddy && cd caddy
-COPY caddy/go.mod caddy/go.sum ./caddy/
+COPY --link caddy/go.mod caddy/go.sum ./caddy/
 
 RUN cd caddy && go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
 
-COPY *.* ./
-COPY caddy caddy
-COPY C-Thread-Pool C-Thread-Pool
-COPY internal internal
-COPY testdata testdata
+COPY --link *.* ./
+COPY --link caddy caddy
+COPY --link C-Thread-Pool C-Thread-Pool
+COPY --link internal internal
+COPY --link testdata testdata
 
 # todo: automate this?
 # see https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 for PHP values
 ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" CGO_CFLAGS=$PHP_CFLAGS CGO_CPPFLAGS=$PHP_CPPFLAGS
 
 RUN cd caddy/frankenphp && \
-    go build -ldflags "-X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
-    cp frankenphp /usr/local/bin && \
-    cp Caddyfile /etc/Caddyfile && \
+    GOBIN=/usr/local/bin go install -ldflags "-X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
+    setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
+    cp Caddyfile /etc/caddy/Caddyfile && \
     frankenphp version
 
-ENTRYPOINT ["/bin/bash","-c"]
 
-FROM php-base AS runner
+FROM common AS runner
 
 ENV GODEBUG=cgocheck=0
 
-COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
-
-WORKDIR /app
-
-RUN mkdir -p /app/public
-RUN echo '<?php phpinfo();' > /app/public/index.php
-
 COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
-COPY --from=builder /etc/Caddyfile /etc/Caddyfile
-
-COPY --from=php-base /usr/local/include/php/ /usr/local/include/php
-COPY --from=php-base /usr/local/lib/libphp.* /usr/local/lib
-COPY --from=php-base /usr/local/lib/php/ /usr/local/lib/php
-COPY --from=php-base /usr/local/php/ /usr/local/php
-COPY --from=php-base /usr/local/bin/ /usr/local/bin
-COPY --from=php-base /usr/src /usr/src
-
-RUN sed -i 's/php/frankenphp run/g' /usr/local/bin/docker-php-entrypoint
-
-CMD [ "--config", "/etc/Caddyfile" ]
+RUN setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
+	frankenphp version

+ 54 - 33
alpine.Dockerfile

@@ -1,10 +1,50 @@
 # syntax=docker/dockerfile:1
-FROM php-base AS builder
+FROM php-base AS common
+
+WORKDIR /app
+
+RUN apk add --no-cache \
+	ca-certificates \
+	libcap \
+	mailcap
+
+RUN set -eux; \
+	mkdir -p \
+		/app/public \
+		/config/caddy \
+		/data/caddy \
+		/etc/caddy; \
+	sed -i 's/php/frankenphp run/g' /usr/local/bin/docker-php-entrypoint; \
+	echo '<?php phpinfo();' > /app/public/index.php
+
+COPY --link caddy/frankenphp/Caddyfile /etc/caddy/Caddyfile
+COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
+
+CMD ["--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
+HEALTHCHECK CMD curl -f https://localhost/healthz || exit 1
+
+# See https://caddyserver.com/docs/conventions#file-locations for details
+ENV XDG_CONFIG_HOME /config
+ENV XDG_DATA_HOME /data
+
+EXPOSE 80
+EXPOSE 443
+EXPOSE 443/udp
+EXPOSE 2019
+
+LABEL org.opencontainers.image.title=FrankenPHP
+LABEL org.opencontainers.image.description="The modern PHP app server"
+LABEL org.opencontainers.image.url=https://frankenphp.dev
+LABEL org.opencontainers.image.source=https://github.com/dunglas/frankenphp
+LABEL org.opencontainers.image.licenses=MIT
+LABEL org.opencontainers.image.vendor="Kévin Dunglas"
+
+
+FROM common AS builder
 
 ARG FRANKENPHP_VERSION='dev'
 
-COPY --from=golang-base /usr/local/go/bin/go /usr/local/go/bin/go
-COPY --from=golang-base /usr/local/go /usr/local/go
+COPY --link --from=golang-base /usr/local/go /usr/local/go
 
 ENV PATH /usr/local/go/bin:$PATH
 
@@ -24,7 +64,7 @@ RUN apk add --no-cache --virtual .build-deps \
 
 WORKDIR /go/src/app
 
-COPY go.mod go.sum ./
+COPY --link go.mod go.sum ./
 RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
 
 RUN mkdir caddy && cd caddy
@@ -32,45 +72,26 @@ COPY caddy/go.mod caddy/go.sum ./caddy/
 
 RUN cd caddy && go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
 
-COPY *.* ./
-COPY caddy caddy
-COPY C-Thread-Pool C-Thread-Pool
-COPY internal internal
-COPY testdata testdata
+COPY --link *.* ./
+COPY --link caddy caddy
+COPY --link C-Thread-Pool C-Thread-Pool
+COPY --link internal internal
+COPY --link testdata testdata
 
 # todo: automate this?
 # see https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 for php values
 ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" CGO_CFLAGS=$PHP_CFLAGS CGO_CPPFLAGS=$PHP_CPPFLAGS
 
 RUN cd caddy/frankenphp && \
-	go build -ldflags "-X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
-	cp frankenphp /usr/local/bin && \
-	cp Caddyfile /etc/Caddyfile && \
+	GOBIN=/usr/local/bin go install -ldflags "-X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
+	setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
 	frankenphp version
 
-ENTRYPOINT ["/bin/sh","-c"]
 
-FROM php-base AS runner
+FROM common AS runner
 
 ENV GODEBUG=cgocheck=0
 
-COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
-
-WORKDIR /app
-
-RUN mkdir -p /app/public
-RUN echo '<?php phpinfo();' > /app/public/index.php
-
 COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
-COPY --from=builder /etc/Caddyfile /etc/Caddyfile
-
-COPY --from=php-base /usr/local/include/php/ /usr/local/include/php
-COPY --from=php-base /usr/local/lib/libphp.* /usr/local/lib
-COPY --from=php-base /usr/local/lib/php/ /usr/local/lib/php
-COPY --from=php-base /usr/local/php/ /usr/local/php
-COPY --from=php-base /usr/local/bin/ /usr/local/bin
-COPY --from=php-base /usr/src /usr/src
-
-RUN sed -i 's/php/frankenphp run/g' /usr/local/bin/docker-php-entrypoint
-
-CMD [ "--config", "/etc/Caddyfile" ]
+RUN setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
+	frankenphp version

+ 33 - 17
caddy/frankenphp/Caddyfile

@@ -9,24 +9,40 @@
 
 {$SERVER_NAME:localhost}
 
-log
+log {
+	# Redact the authorization query parameter that can be set by Mercure
+	format filter {
+		wrap console
+		fields {
+			uri query {
+				replace authorization REDACTED
+			}
+		}
+	}
+}
+
 route {
-	root * public/ 
-	mercure {
-        # Transport to use (default to Bolt)
-        transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
-        # Publisher JWT key
-        publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
-        # Subscriber JWT key
-        subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
-        # Allow anonymous subscribers (double-check that it's what you want)
-        anonymous
-        # Enable the subscription API (double-check that it's what you want)
-        subscriptions
-        # Extra directives
-        {$MERCURE_EXTRA_DIRECTIVES}
-    }
-    vulcain
+	# Healthcheck URL
+	skip_log /healthz
+	respond /healthz 200
+
+	root * public/
+	# Uncomment the following lines to enable Mercure and Vulcain modules
+	#mercure {
+	#	# Transport to use (default to Bolt)
+	#	transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
+	#	# Publisher JWT key
+	#	publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
+	#	# Subscriber JWT key
+	#	subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
+	#	# Allow anonymous subscribers (double-check that it's what you want)
+	#	anonymous
+	#	# Enable the subscription API (double-check that it's what you want)
+	#	subscriptions
+	#	# Extra directives
+	#	{$MERCURE_EXTRA_DIRECTIVES}
+	#}
+	#vulcain
 
 	# Add trailing slash for directory requests
 	@canonicalPath {

+ 0 - 6
docker-bake.hcl

@@ -81,12 +81,6 @@ target "default" {
         [for v in semver(VERSION) : tag(v, os, php-version, tgt)]
     ]))
     labels = {
-        "org.opencontainers.image.title" = "FrankenPHP"
-        "org.opencontainers.image.description" = "The modern PHP app server"
-        "org.opencontainers.image.url" = "https://frankenphp.dev"
-        "org.opencontainers.image.source" = "https://github.com/dunglas/frankenphp"
-        "org.opencontainers.image.licenses" = "MIT"
-        "org.opencontainers.image.vendor" = "Kévin Dunglas"
         "org.opencontainers.image.created" = "${timestamp()}"
         "org.opencontainers.image.version" = VERSION
         "org.opencontainers.image.revision" = SHA