Browse Source

feat: add Alpine based Docker image (#43)

* Gitignore .idea folder (PhpStorm etc)

* Alpine version of Dockerfile

* Bake definition to build Docker images

* Docs for Docker image building

* Link to docker.md

* Use latest change on using official php-src repo and PHP-8.2 branch

* Remove ARGS and get other changes from Dockerfile (original)

* Update GHA workflows with Dockerfile.alpine
Marko Korhonen 2 years ago
parent
commit
4293397541
7 changed files with 210 additions and 4 deletions
  1. 8 2
      .github/workflows/push.yaml
  2. 8 2
      .github/workflows/tests.yaml
  3. 1 0
      .gitignore
  4. 133 0
      Dockerfile.alpine
  5. 1 0
      README.md
  6. 29 0
      docker-bake.hcl
  7. 30 0
      docs/docker.md

+ 8 - 2
.github/workflows/push.yaml

@@ -8,6 +8,9 @@ on:
 jobs:
 jobs:
   docker-tests:
   docker-tests:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        dockerfile: [ "Dockerfile", "Dockerfile.alpine" ]
     steps:
     steps:
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
         with:
         with:
@@ -23,7 +26,7 @@ jobs:
         uses: docker/build-push-action@v3
         uses: docker/build-push-action@v3
         with:
         with:
           context: ./
           context: ./
-          file: Dockerfile
+          file: ${{ matrix.dockerfile }}
           push: false
           push: false
           pull: true
           pull: true
           target: builder
           target: builder
@@ -39,6 +42,9 @@ jobs:
           docker run --rm frankenphp:${{ github.sha }}-builder "go test"
           docker run --rm frankenphp:${{ github.sha }}-builder "go test"
   push-image:
   push-image:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        dockerfile: [ "Dockerfile", "Dockerfile.alpine" ]
     steps:
     steps:
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
         with:
         with:
@@ -81,7 +87,7 @@ jobs:
         uses: docker/build-push-action@v3
         uses: docker/build-push-action@v3
         with:
         with:
           context: ./
           context: ./
-          file: Dockerfile
+          file: ${{ matrix.dockerfile }}
           push: true
           push: true
           pull: true
           pull: true
           target: final
           target: final

+ 8 - 2
.github/workflows/tests.yaml

@@ -6,6 +6,9 @@ on:
 jobs:
 jobs:
   docker-tests:
   docker-tests:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        dockerfile: [ "Dockerfile", "Dockerfile.alpine" ]
     steps:
     steps:
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
         with:
         with:
@@ -21,7 +24,7 @@ jobs:
         uses: docker/build-push-action@v3
         uses: docker/build-push-action@v3
         with:
         with:
           context: ./
           context: ./
-          file: Dockerfile
+          file: ${{ matrix.dockerfile }}
           push: false
           push: false
           pull: true
           pull: true
           target: builder
           target: builder
@@ -37,6 +40,9 @@ jobs:
           docker run --rm frankenphp:${{ github.sha }}-builder "go test"
           docker run --rm frankenphp:${{ github.sha }}-builder "go test"
   push-image:
   push-image:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        dockerfile: [ "Dockerfile", "Dockerfile.alpine" ]
     steps:
     steps:
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
         with:
         with:
@@ -72,7 +78,7 @@ jobs:
         uses: docker/build-push-action@v3
         uses: docker/build-push-action@v3
         with:
         with:
           context: ./
           context: ./
-          file: Dockerfile
+          file: ${{ matrix.dockerfile }}
           push: false
           push: false
           pull: true
           pull: true
           target: final
           target: final

+ 1 - 0
.gitignore

@@ -1,4 +1,5 @@
 /caddy/frankenphp/frankenphp
 /caddy/frankenphp/frankenphp
 /internal/testserver/testserver
 /internal/testserver/testserver
+.idea/
 .vscode/
 .vscode/
 __debug_bin
 __debug_bin

+ 133 - 0
Dockerfile.alpine

@@ -0,0 +1,133 @@
+FROM php:8.2.0RC4-zts-alpine3.16 AS php-base
+
+# Note that this image is based on the official PHP image, once 8.3 is released, this stage can likely be removed
+
+RUN rm -Rf /usr/local/include/php/ /usr/local/lib/libphp.* /usr/local/lib/php/ /usr/local/php/
+
+ENV PHPIZE_DEPS \
+    autoconf \
+    dpkg-dev dpkg \
+    file \
+    g++ \
+    gcc \
+    libc-dev \
+    make \
+    pkgconf \
+    re2c
+
+RUN apk add --no-cache --virtual .build-deps \
+    $PHPIZE_DEPS \
+    argon2-dev \
+    coreutils \
+    curl-dev \
+    readline-dev \
+    libsodium-dev \
+    sqlite-dev \
+    openssl-dev \
+    libxml2-dev \
+    gnu-libiconv-dev \
+    linux-headers \
+    oniguruma-dev \
+    bison \
+    git
+
+RUN git clone --depth=1 --single-branch --branch=PHP-8.2 https://github.com/php/php-src.git
+
+WORKDIR /php-src/
+
+# --enable-embed is only necessary to generate libphp.so, we don't use this SAPI directly
+RUN ./buildconf
+RUN ./configure \
+        --enable-embed \
+        --enable-zts \
+        --disable-zend-signals \
+    	# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
+    	--enable-mysqlnd \
+     	# make sure invalid --configure-flags are fatal errors instead of just warnings
+    	--enable-option-checking=fatal \
+    	# https://github.com/docker-library/php/issues/439
+    	--with-mhash \
+    	# https://github.com/docker-library/php/issues/822
+    	--with-pic \
+    	# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
+    	--enable-ftp \
+    	# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
+    	--enable-mbstring \
+    	# https://wiki.php.net/rfc/argon2_password_hash
+    	--with-password-argon2 \
+    	# https://wiki.php.net/rfc/libsodium
+    	--with-sodium=shared \
+    	# always build against system sqlite3 (https://github.com/php/php-src/commit/6083a387a81dbbd66d6316a3a12a63f06d5f7109)
+		--with-pdo-sqlite=/usr \
+		--with-sqlite3=/usr \
+		--with-curl \
+		--with-iconv \
+		--with-openssl \
+		--with-readline \
+		--with-zlib \
+    	# https://github.com/bwoebi/phpdbg-docs/issues/1#issuecomment-163872806 ("phpdbg is primarily a CLI debugger, and is not suitable for debugging an fpm stack.")
+		--disable-phpdbg \
+        --with-config-file-path="$PHP_INI_DIR" \
+        --with-config-file-scan-dir="$PHP_INI_DIR/conf.d"
+RUN make -j$(nproc)
+RUN make install
+RUN rm -Rf /php-src/
+RUN echo "Creating src archive for building extensions\n"
+RUN tar -c -f /usr/src/php.tar.xz -J /php-src/
+#RUN ldconfig
+RUN php --version
+
+FROM php-base AS builder
+
+COPY --from=golang:alpine3.16 /usr/local/go/bin/go /usr/local/bin/go
+COPY --from=golang:alpine3.16 /usr/local/go /usr/local/go
+
+WORKDIR /go/src/app
+
+COPY 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/
+
+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
+
+# todo: automate this?
+# see https://github.com/docker-library/php/blob/master/8.2-rc/bullseye/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 && \
+    cp frankenphp /usr/local/bin && \
+    cp /go/src/app/caddy/frankenphp/Caddyfile /etc/Caddyfile
+
+ENTRYPOINT ["/bin/bash","-c"]
+
+FROM php:8.2.0RC4-zts-alpine3.16 AS final
+
+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" ]

+ 1 - 0
README.md

@@ -35,6 +35,7 @@ Go to `https://localhost`, and enjoy!
 * [Real-time](docs/mercure.md)
 * [Real-time](docs/mercure.md)
 * [Configuration](docs/config.md)
 * [Configuration](docs/config.md)
 * [Demo app (Symfony) and benchmarks](https://github.com/dunglas/frankenphp-demo)
 * [Demo app (Symfony) and benchmarks](https://github.com/dunglas/frankenphp-demo)
+* [Building Docker images](docs/docker.md)
 * [Compile from sources](docs/compile.md)
 * [Compile from sources](docs/compile.md)
 * [Go library documentation](https://pkg.go.dev/github.com/dunglas/frankenphp)
 * [Go library documentation](https://pkg.go.dev/github.com/dunglas/frankenphp)
 * [Contributing and debugging](CONTRIBUTING.md)
 * [Contributing and debugging](CONTRIBUTING.md)

+ 29 - 0
docker-bake.hcl

@@ -0,0 +1,29 @@
+variable "REPO_NAME" {
+    default = "dunglas/frankenphp"
+}
+
+group "default" {
+    targets = ["bullseye", "alpine"]
+}
+
+target "common" {
+    platforms = ["linux/amd64", "linux/arm64"]
+}
+
+#
+# FrankenPHP
+#
+
+target "bullseye" {
+    inherits = ["common"]
+    context = "."
+    dockerfile = "Dockerfile"
+    tags = ["${REPO_NAME}:bullseye", "${REPO_NAME}:latest"]
+}
+
+target "alpine" {
+    inherits = ["common"]
+    context = "."
+    dockerfile = "Dockerfile.alpine"
+    tags = ["${REPO_NAME}:alpine"]
+}

+ 30 - 0
docs/docker.md

@@ -0,0 +1,30 @@
+# Building Docker images
+
+Print bake plan:
+
+```
+docker buildx bake -f docker-bake.hcl --print
+```
+
+Build FrankenPHP images for amd64 locally:
+
+```
+docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/amd64"
+```
+
+Build FrankenPHP images for arm64 locally:
+
+```
+docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/arm64"
+```
+
+Build FrankenPHP images from scratch for arm64 & amd64 and push to Docker Hub:
+
+```
+docker buildx bake -f docker-bake.hcl --pull --no-cache --push
+```
+
+## Resources
+
+* [Bake file definition](https://docs.docker.com/build/customize/bake/file-definition/)
+* [docker buildx build](https://docs.docker.com/engine/reference/commandline/buildx_build/)