diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 0c8d684..1873a70 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -7,144 +7,567 @@ on: - cron: "0 0 * * 0" jobs: - build: + # =========================================== + # Alpine: Build and Test (all variants per version) + # =========================================== + build-test-alpine: runs-on: ubuntu-latest strategy: matrix: version: ["8.1", "8.2", "8.3", "8.4"] - type: ["", "-prod"] steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v4 - name: Setup QEMU uses: docker/setup-qemu-action@v3 - - name: Setup Docker Buildx + - name: Setup Docker Buildx (docker driver for local builds) uses: docker/setup-buildx-action@v3 + with: + driver: docker - - name: Login to DockerHub - uses: docker/login-action@v3 - if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' + # ======================================== + # BASE DEV IMAGE + # ======================================== + - name: Build base dev image + uses: docker/build-push-action@v6 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} + context: ${{ matrix.version }} + load: true + tags: kooldev/php:${{ matrix.version }} + + - name: Tests (base dev) - Basic + run: | + docker run kooldev/php:${{ matrix.version }} php -v + docker run kooldev/php:${{ matrix.version }} composer -V + docker run kooldev/php:${{ matrix.version }} composer1 -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }} php -v + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }} composer -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }} composer1 -V + docker run kooldev/php:${{ matrix.version }} php -m | grep readline + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }} php -m + + - name: Tests (base dev) - Dockerize + run: | + docker run kooldev/php:${{ matrix.version }} dockerize --version + docker run kooldev/php:${{ matrix.version }} sh -c 'echo "{{ .Env.TEST_VAR }}" > /tmp/test.tmpl && TEST_VAR=hello dockerize -template /tmp/test.tmpl:/tmp/test.out && cat /tmp/test.out | grep hello' + + - name: Tests (base dev) - PHP Extensions + run: | + docker run kooldev/php:${{ matrix.version }} php -m | grep -i bcmath + docker run kooldev/php:${{ matrix.version }} php -m | grep -i gd + docker run kooldev/php:${{ matrix.version }} php -m | grep -i intl + docker run kooldev/php:${{ matrix.version }} php -m | grep -i pdo_mysql + docker run kooldev/php:${{ matrix.version }} php -m | grep -i pdo_pgsql + docker run kooldev/php:${{ matrix.version }} php -m | grep -i redis + docker run kooldev/php:${{ matrix.version }} php -m | grep -i zip + docker run kooldev/php:${{ matrix.version }} php -m | grep -i mbstring + docker run kooldev/php:${{ matrix.version }} php -m | grep -i ldap - - name: Build and export to Docker + - name: Tests (base dev) - Development Checks + run: | + docker run kooldev/php:${{ matrix.version }} php -m | grep -i pcov + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }} php -m | grep -i xdebug + + # ======================================== + # BASE PROD IMAGE + # ======================================== + - name: Build base prod image uses: docker/build-push-action@v6 with: - context: ${{ matrix.version }}${{ matrix.type }} + context: ${{ matrix.version }}-prod load: true - tags: kooldev/php:${{ matrix.version }}${{ matrix.type }} + tags: kooldev/php:${{ matrix.version }}-prod - - name: Tests + - name: Tests (base prod) - Basic run: | - docker run kooldev/php:${{ matrix.version }}${{ matrix.type }} php -v - docker run kooldev/php:${{ matrix.version }}${{ matrix.type }} composer -V - docker run kooldev/php:${{ matrix.version }}${{ matrix.type }} composer1 -V - docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}${{ matrix.type }} php -v - docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}${{ matrix.type }} composer -V - docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}${{ matrix.type }} composer1 -V - docker run kooldev/php:${{ matrix.version }}${{ matrix.type }} php -m | grep readline - docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}${{ matrix.type }} php -m + docker run kooldev/php:${{ matrix.version }}-prod php -v + docker run kooldev/php:${{ matrix.version }}-prod composer -V + docker run kooldev/php:${{ matrix.version }}-prod composer1 -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-prod php -v + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-prod composer -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-prod composer1 -V + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep readline + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}-prod php -m - - name: Build and push + - name: Tests (base prod) - Dockerize + run: | + docker run kooldev/php:${{ matrix.version }}-prod dockerize --version + docker run kooldev/php:${{ matrix.version }}-prod sh -c 'echo "{{ .Env.TEST_VAR }}" > /tmp/test.tmpl && TEST_VAR=hello dockerize -template /tmp/test.tmpl:/tmp/test.out && cat /tmp/test.out | grep hello' + + - name: Tests (base prod) - PHP Extensions + run: | + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i bcmath + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i gd + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i intl + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i pdo_mysql + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i pdo_pgsql + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i redis + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i zip + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i mbstring + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i ldap + + - name: Tests (base prod) - Production Checks + run: | + docker run kooldev/php:${{ matrix.version }}-prod php -m | grep -i "Zend OPcache" + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}-prod php -m | grep -i xdebug && exit 1 || echo "OK: xdebug not in prod" + + # ======================================== + # NGINX DEV IMAGE (uses local base dev) + # ======================================== + - name: Build nginx dev image uses: docker/build-push-action@v6 - if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' with: - context: ${{ matrix.version }}${{ matrix.type }} - platforms: linux/amd64,linux/arm64 - push: true - tags: kooldev/php:${{ matrix.version }}${{ matrix.type }} + context: ${{ matrix.version }}-nginx + load: true + tags: kooldev/php:${{ matrix.version }}-nginx + + - name: Tests (nginx dev) - Basic + run: | + docker run kooldev/php:${{ matrix.version }}-nginx php -v + docker run kooldev/php:${{ matrix.version }}-nginx composer -V + docker run kooldev/php:${{ matrix.version }}-nginx composer1 -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx php -v + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx composer -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx composer1 -V + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep readline + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}-nginx php -m + docker run kooldev/php:${{ matrix.version }}-nginx nginx -v + docker run kooldev/php:${{ matrix.version }}-nginx nginx -T + docker run kooldev/php:${{ matrix.version }}-nginx supervisord --version - - name: Build and export to Docker (nginx) + - name: Tests (nginx dev) - Dockerize + run: | + docker run kooldev/php:${{ matrix.version }}-nginx dockerize --version + docker run kooldev/php:${{ matrix.version }}-nginx sh -c 'echo "{{ .Env.TEST_VAR }}" > /tmp/test.tmpl && TEST_VAR=hello dockerize -template /tmp/test.tmpl:/tmp/test.out && cat /tmp/test.out | grep hello' + + - name: Tests (nginx dev) - PHP Extensions + run: | + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i bcmath + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i gd + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i intl + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i pdo_mysql + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i pdo_pgsql + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i redis + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i zip + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i mbstring + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i ldap + + - name: Tests (nginx dev) - Development Checks + run: | + docker run kooldev/php:${{ matrix.version }}-nginx php -m | grep -i pcov + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}-nginx php -m | grep -i xdebug + + # ======================================== + # NGINX PROD IMAGE (uses local base prod) + # ======================================== + - name: Build nginx prod image uses: docker/build-push-action@v6 with: - context: ${{ matrix.version }}-nginx${{ matrix.type }} + context: ${{ matrix.version }}-nginx-prod load: true - tags: kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} + tags: kooldev/php:${{ matrix.version }}-nginx-prod + + - name: Tests (nginx prod) - Basic + run: | + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -v + docker run kooldev/php:${{ matrix.version }}-nginx-prod composer -V + docker run kooldev/php:${{ matrix.version }}-nginx-prod composer1 -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx-prod php -v + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx-prod composer -V + docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx-prod composer1 -V + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep readline + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}-nginx-prod php -m + docker run kooldev/php:${{ matrix.version }}-nginx-prod nginx -v + docker run kooldev/php:${{ matrix.version }}-nginx-prod nginx -T + docker run kooldev/php:${{ matrix.version }}-nginx-prod supervisord --version + + - name: Tests (nginx prod) - Dockerize + run: | + docker run kooldev/php:${{ matrix.version }}-nginx-prod dockerize --version + docker run kooldev/php:${{ matrix.version }}-nginx-prod sh -c 'echo "{{ .Env.TEST_VAR }}" > /tmp/test.tmpl && TEST_VAR=hello dockerize -template /tmp/test.tmpl:/tmp/test.out && cat /tmp/test.out | grep hello' + + - name: Tests (nginx prod) - PHP Extensions + run: | + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i bcmath + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i gd + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i intl + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i pdo_mysql + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i pdo_pgsql + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i redis + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i zip + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i mbstring + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i ldap + + - name: Tests (nginx prod) - Production Checks + run: | + docker run kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i "Zend OPcache" + docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}-nginx-prod php -m | grep -i xdebug && exit 1 || echo "OK: xdebug not in prod" - - name: Build and export to Docker (Node) + # ======================================== + # NODE IMAGE (uses local base dev) + # ======================================== + - name: Build node image uses: docker/build-push-action@v6 - if: matrix.type == '' with: - context: ${{ matrix.version }}-node${{ matrix.type }} + context: ${{ matrix.version }}-node load: true - tags: kooldev/php:${{ matrix.version }}-node${{ matrix.type }} + tags: kooldev/php:${{ matrix.version }}-node - - name: Tests (Node) - if: matrix.type == '' + - name: Tests (node) - Basic run: | - docker run kooldev/php:${{ matrix.version }}-node${{ matrix.type }} node -v - docker run kooldev/php:${{ matrix.version }}-node${{ matrix.type }} npm -v - docker run kooldev/php:${{ matrix.version }}-node${{ matrix.type }} yarn -v + docker run kooldev/php:${{ matrix.version }}-node node -v + docker run kooldev/php:${{ matrix.version }}-node npm -v + docker run kooldev/php:${{ matrix.version }}-node yarn -v + + # =========================================== + # Debian: Build and Test (base + nginx per type) + # =========================================== + build-test-debian: + runs-on: ubuntu-latest + + strategy: + matrix: + type: ["", "-prod"] - - name: Tests (nginx) + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker Buildx (docker driver for local builds) + uses: docker/setup-buildx-action@v3 + with: + driver: docker + + # ======================================== + # BASE IMAGE (DEBIAN) + # ======================================== + - name: Build base image (Debian) + uses: docker/build-push-action@v6 + with: + context: 8.4-debian${{ matrix.type }} + load: true + tags: kooldev/php:8.4-debian${{ matrix.type }} + + - name: Tests (Debian base) - Basic run: | - docker run kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} php -v - docker run kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} composer -V - docker run kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} composer1 -V - docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} php -v - docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} composer -V - docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} composer1 -V - docker run -e ASUSER=1000 kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} dockerize --version + docker run kooldev/php:8.4-debian${{ matrix.type }} php -v + docker run kooldev/php:8.4-debian${{ matrix.type }} composer -V + docker run kooldev/php:8.4-debian${{ matrix.type }} composer1 -V + docker run -e ASUSER=1000 kooldev/php:8.4-debian${{ matrix.type }} php -v + docker run -e ASUSER=1000 kooldev/php:8.4-debian${{ matrix.type }} composer -V + docker run -e ASUSER=1000 kooldev/php:8.4-debian${{ matrix.type }} composer1 -V + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep readline + docker run -e ENABLE_XDEBUG=true kooldev/php:8.4-debian${{ matrix.type }} php -m - docker run kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} php -m | grep readline - docker run -e ENABLE_XDEBUG=true kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} php -m + - name: Tests (Debian base) - Dockerize + run: | + docker run kooldev/php:8.4-debian${{ matrix.type }} dockerize --version + docker run kooldev/php:8.4-debian${{ matrix.type }} bash -c 'echo "{{ .Env.TEST_VAR }}" > /tmp/test.tmpl && TEST_VAR=hello dockerize -template /tmp/test.tmpl:/tmp/test.out && cat /tmp/test.out | grep hello' + + - name: Tests (Debian base) - Gosu user switching + run: | + docker run kooldev/php:8.4-debian${{ matrix.type }} gosu --version + docker run -e ASUSER=1000 kooldev/php:8.4-debian${{ matrix.type }} id | grep "uid=1000" - docker run kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} nginx -v - docker run kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} nginx -T - docker run kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} supervisord --version + - name: Tests (Debian base) - PHP Extensions + run: | + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i bcmath + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i gd + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i intl + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i pdo_mysql + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i pdo_pgsql + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i redis + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i zip + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i mbstring + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i ldap - - name: Build and push (nginx) + - name: Tests (Debian base) - Production Checks + if: matrix.type == '-prod' + run: | + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i "Zend OPcache" + docker run -e ENABLE_XDEBUG=true kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i xdebug && exit 1 || echo "OK: xdebug not in prod" + + - name: Tests (Debian base) - Development Checks + if: matrix.type == '' + run: | + docker run kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i pcov + docker run -e ENABLE_XDEBUG=true kooldev/php:8.4-debian${{ matrix.type }} php -m | grep -i xdebug + + # ======================================== + # NGINX IMAGE (DEBIAN - uses local base) + # ======================================== + - name: Build nginx image (Debian) uses: docker/build-push-action@v6 - if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' with: - context: ${{ matrix.version }}-nginx${{ matrix.type }} + context: 8.4-debian-nginx${{ matrix.type }} + load: true + tags: kooldev/php:8.4-debian-nginx${{ matrix.type }} + + - name: Tests (Debian nginx) - Basic + run: | + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -v + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} composer -V + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} composer1 -V + docker run -e ASUSER=1000 kooldev/php:8.4-debian-nginx${{ matrix.type }} php -v + docker run -e ASUSER=1000 kooldev/php:8.4-debian-nginx${{ matrix.type }} composer -V + docker run -e ASUSER=1000 kooldev/php:8.4-debian-nginx${{ matrix.type }} composer1 -V + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep readline + docker run -e ENABLE_XDEBUG=true kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} nginx -v + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} nginx -T + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} supervisord --version + + - name: Tests (Debian nginx) - Dockerize + run: | + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} dockerize --version + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} bash -c 'echo "{{ .Env.TEST_VAR }}" > /tmp/test.tmpl && TEST_VAR=hello dockerize -template /tmp/test.tmpl:/tmp/test.out && cat /tmp/test.out | grep hello' + + - name: Tests (Debian nginx) - PHP Extensions + run: | + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i bcmath + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i gd + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i intl + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i pdo_mysql + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i pdo_pgsql + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i redis + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i zip + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i mbstring + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i ldap + + - name: Tests (Debian nginx) - Production Checks + if: matrix.type == '-prod' + run: | + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i "Zend OPcache" + docker run -e ENABLE_XDEBUG=true kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i xdebug && exit 1 || echo "OK: xdebug not in prod" + + - name: Tests (Debian nginx) - Development Checks + if: matrix.type == '' + run: | + docker run kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i pcov + docker run -e ENABLE_XDEBUG=true kooldev/php:8.4-debian-nginx${{ matrix.type }} php -m | grep -i xdebug + + # =========================================== + # PUSH JOBS (master branch only) + # =========================================== + # These jobs use docker-container driver (default) for multi-arch builds. + # They rebuild images because docker-container driver cannot access + # locally built images from the test jobs. + + # ------------------------------------------- + # Alpine Push: Base Images + # ------------------------------------------- + push-alpine-base: + needs: build-test-alpine + if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' + runs-on: ubuntu-latest + + strategy: + matrix: + version: ["8.1", "8.2", "8.3", "8.4"] + type: ["", "-prod"] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Push base image + uses: docker/build-push-action@v6 + with: + context: ${{ matrix.version }}${{ matrix.type }} + push: true platforms: linux/amd64,linux/arm64 + tags: kooldev/php:${{ matrix.version }}${{ matrix.type }} + + # ------------------------------------------- + # Alpine Push: Nginx Images (depends on base) + # ------------------------------------------- + push-alpine-nginx: + needs: push-alpine-base + if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' + runs-on: ubuntu-latest + + strategy: + matrix: + version: ["8.1", "8.2", "8.3", "8.4"] + type: ["", "-prod"] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Push nginx image + uses: docker/build-push-action@v6 + with: + context: ${{ matrix.version }}-nginx${{ matrix.type }} push: true + platforms: linux/amd64,linux/arm64 tags: kooldev/php:${{ matrix.version }}-nginx${{ matrix.type }} - - name: Build and push (Node) + # ------------------------------------------- + # Alpine Push: Node Images (depends on base) + # ------------------------------------------- + push-alpine-node: + needs: push-alpine-base + if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' + runs-on: ubuntu-latest + + strategy: + matrix: + version: ["8.1", "8.2", "8.3", "8.4"] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Push node image uses: docker/build-push-action@v6 - if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' && matrix.type == '' with: - context: ${{ matrix.version }}-node${{ matrix.type }} + context: ${{ matrix.version }}-node + push: true platforms: linux/amd64,linux/arm64 + tags: kooldev/php:${{ matrix.version }}-node + + # ------------------------------------------- + # Debian Push: Base Images + # ------------------------------------------- + push-debian-base: + needs: build-test-debian + if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' + runs-on: ubuntu-latest + + strategy: + matrix: + type: ["", "-prod"] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Push base image (Debian) + uses: docker/build-push-action@v6 + with: + context: 8.4-debian${{ matrix.type }} push: true - tags: kooldev/php:${{ matrix.version }}-node${{ matrix.type }} + platforms: linux/amd64,linux/arm64 + tags: kooldev/php:8.4-debian${{ matrix.type }} - trigger-build-wordpress: - name: Trigger Wordpress Build + # ------------------------------------------- + # Debian Push: Nginx Images (depends on base) + # ------------------------------------------- + push-debian-nginx: + needs: push-debian-base + if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' runs-on: ubuntu-latest - needs: build + + strategy: + matrix: + type: ["", "-prod"] + steps: - - name: Trigger build on kool-dev/docker-wordpress - uses: benc-uk/workflow-dispatch@v1.2 - if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 with: - workflow: CI/CD - repo: kool-dev/docker-wordpress - token: ${{ secrets.WORKFLOW_TOKEN }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} - trigger-extended-builds: - name: Trigger Extended Builds + - name: Push nginx image (Debian) + uses: docker/build-push-action@v6 + with: + context: 8.4-debian-nginx${{ matrix.type }} + push: true + platforms: linux/amd64,linux/arm64 + tags: kooldev/php:8.4-debian-nginx${{ matrix.type }} + + # =========================================== + # DOWNSTREAM TRIGGERS (master branch only) + # =========================================== + # These jobs trigger builds in dependent repositories after all + # images have been successfully pushed to Docker Hub. + + trigger-downstream: + needs: + - push-alpine-nginx + - push-alpine-node + - push-debian-nginx + if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' runs-on: ubuntu-latest - needs: build + strategy: matrix: - image: + repo: + - kool-dev/docker-wordpress - kool-dev/docker-php-sqlsrv - kool-dev/docker-php-swoole - kool-dev/docker-phpqa + steps: - - name: Trigger build on ${{ matrix.image }} - uses: benc-uk/workflow-dispatch@v1.2 - if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php' - with: - workflow: CI/CD - ref: refs/heads/main - repo: ${{ matrix.image }} - token: ${{ secrets.WORKFLOW_TOKEN }} + - name: Trigger ${{ matrix.repo }} + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ secrets.DISPATCH_TOKEN }} + repository: ${{ matrix.repo }} + event-type: docker-php-updated diff --git a/8.1-nginx-prod/default.tmpl b/8.1-nginx-prod/default.tmpl index ccafaf3..9992154 100644 --- a/8.1-nginx-prod/default.tmpl +++ b/8.1-nginx-prod/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/8.1-nginx/default.tmpl b/8.1-nginx/default.tmpl index ccafaf3..9992154 100644 --- a/8.1-nginx/default.tmpl +++ b/8.1-nginx/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/8.2-nginx-prod/default.tmpl b/8.2-nginx-prod/default.tmpl index ccafaf3..9992154 100644 --- a/8.2-nginx-prod/default.tmpl +++ b/8.2-nginx-prod/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/8.2-nginx/default.tmpl b/8.2-nginx/default.tmpl index ccafaf3..9992154 100644 --- a/8.2-nginx/default.tmpl +++ b/8.2-nginx/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/8.3-nginx-prod/default.tmpl b/8.3-nginx-prod/default.tmpl index ccafaf3..9992154 100644 --- a/8.3-nginx-prod/default.tmpl +++ b/8.3-nginx-prod/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/8.3-nginx/default.tmpl b/8.3-nginx/default.tmpl index ccafaf3..9992154 100644 --- a/8.3-nginx/default.tmpl +++ b/8.3-nginx/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/8.4-debian-nginx-prod/Dockerfile b/8.4-debian-nginx-prod/Dockerfile new file mode 100644 index 0000000..b09ddfc --- /dev/null +++ b/8.4-debian-nginx-prod/Dockerfile @@ -0,0 +1,62 @@ +FROM debian:bookworm AS cert + +WORKDIR /kool/ssl + +RUN apt-get update && \ + apt-get install -y openssl && \ + openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 && \ + openssl rsa -passin pass:x -in server.pass.key -out _.localhost.key && \ + rm server.pass.key && \ + openssl req -new -key _.localhost.key -out server.csr \ + -subj "/C=XX/ST=XX/L=XX/O=Kool-Local/OU=Localhost/CN=*.localhost" && \ + openssl x509 -req -days 365 -in server.csr -signkey _.localhost.key -out _.localhost.crt && \ + openssl x509 -in _.localhost.crt -out _.localhost.pem + +FROM kooldev/php:8.4-debian-prod + +ENV PHP_FPM_LISTEN=/run/php-fpm.sock \ + NGINX_LISTEN=80 \ + NGINX_HTTPS=false \ + NGINX_LISTEN_HTTPS=443 \ + NGINX_HTTPS_CERT=/kool/ssl/_.localhost.pem \ + NGINX_HTTPS_CERT_KEY=/kool/ssl/_.localhost.key \ + NGINX_ROOT=/app/public \ + NGINX_INDEX=index.php \ + NGINX_CLIENT_MAX_BODY_SIZE=25M \ + NGINX_PHP_FPM=unix:/run/php-fpm.sock \ + NGINX_FASTCGI_READ_TIMEOUT=60s \ + NGINX_FASTCGI_BUFFERS='8 8k' \ + NGINX_FASTCGI_BUFFER_SIZE='16k' \ + NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE=true + +RUN apt-get update && apt-get install -y --no-install-recommends supervisor nginx wget \ + && chown -R kool:kool /var/lib/nginx \ + && chmod 770 /var/lib/nginx \ + && ln -sf /dev/stdout /var/log/nginx/access.log \ + && ln -sf /dev/stderr /var/log/nginx/error.log \ + # add h5bp/server-configs-nginx + && mkdir -p /etc/nginx/conf.d \ + && mkdir /etc/nginx/h5bp \ + && cd /etc/nginx/h5bp \ + && wget https://github.com/h5bp/server-configs-nginx/archive/refs/tags/5.0.1.tar.gz -O h5bp.tgz \ + && tar xzvf h5bp.tgz \ + && rm -f h5bp.tgz \ + && mv server-configs-nginx-*/h5bp/* . \ + && mv server-configs-nginx-*/nginx.conf /etc/nginx/nginx.conf \ + && sed -i "s|^user .*|user\ kool kool;|g" /etc/nginx/nginx.conf \ + && mv server-configs-nginx-*/mime.types /etc/nginx/mime.types \ + && rm -rf server-configs-nginx-* \ + && curl -L https://raw.githubusercontent.com/nginxinc/docker-nginx/master/entrypoint/30-tune-worker-processes.sh -o /kool/30-tune-worker-processes.sh \ + && chmod +x /kool/30-tune-worker-processes.sh \ + && apt-get purge -y --auto-remove wget \ + && rm -rf /var/lib/apt/lists/* + +COPY supervisor.conf /kool/supervisor.conf +COPY default.tmpl /kool/default.tmpl +COPY entrypoint /kool/entrypoint +COPY --from=cert /kool/ssl /kool/ssl +RUN chmod +x /kool/entrypoint + +EXPOSE 80 + +CMD [ "supervisord", "-c", "/kool/supervisor.conf" ] diff --git a/8.4-debian-nginx-prod/default.tmpl b/8.4-debian-nginx-prod/default.tmpl new file mode 100644 index 0000000..9992154 --- /dev/null +++ b/8.4-debian-nginx-prod/default.tmpl @@ -0,0 +1,50 @@ +server { + listen {{ .Env.NGINX_LISTEN }} default_server; + server_name _; +{{ if isTrue .Env.NGINX_HTTPS }} + listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; + ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; + ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; +{{ end }} + root {{ .Env.NGINX_ROOT }}; + index {{ .Env.NGINX_INDEX }}; + charset utf-8; + + location = /favicon.ico { log_not_found off; access_log off; } + location = /robots.txt { log_not_found off; access_log off; } + + client_max_body_size {{ .Env.NGINX_CLIENT_MAX_BODY_SIZE }}; + + error_page 404 /index.php; + + location / { + try_files $uri /{{ .Env.NGINX_INDEX }}?$query_string; + } + + location ~ \.php$ { + fastcgi_buffers {{ .Env.NGINX_FASTCGI_BUFFERS }}; + fastcgi_buffer_size {{ .Env.NGINX_FASTCGI_BUFFER_SIZE }}; + fastcgi_pass {{ .Env.NGINX_PHP_FPM }}; + fastcgi_read_timeout {{ .Env.NGINX_FASTCGI_READ_TIMEOUT }}; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.ht { + deny all; + } + + # good practices + add_header X-Frame-Options "SAMEORIGIN"; + + # basic H5BP suggestions + include h5bp/security/referrer-policy.conf; + include h5bp/security/x-content-type-options.conf; + include h5bp/cross-origin/requests.conf; + + # performance enhancements (mostly for caching static data) + include h5bp/web_performance/cache-file-descriptors.conf; + include h5bp/web_performance/compression.conf; +} diff --git a/8.4-debian-nginx-prod/entrypoint b/8.4-debian-nginx-prod/entrypoint new file mode 100644 index 0000000..12ba331 --- /dev/null +++ b/8.4-debian-nginx-prod/entrypoint @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + + +# Run as current user +CURRENT_USER=${ASUSER:-${UID:-0}} + +if [ ! -z "$CURRENT_USER" ] && [ "$CURRENT_USER" != "0" ]; then + usermod -u $CURRENT_USER kool +fi + +dockerize -template /kool/kool.tmpl:/usr/local/etc/php/conf.d/kool.ini -template /kool/zz-docker.tmpl:/usr/local/etc/php-fpm.d/zz-docker.conf -template /kool/default.tmpl:/etc/nginx/conf.d/default.conf + +/kool/30-tune-worker-processes.sh + +# Run entrypoint if provided +if [ ! -z "$ENTRYPOINT" ] && [ -f "$ENTRYPOINT" ]; then + bash $ENTRYPOINT +fi + +if [ "$1" = "sh" ] || [ "$1" = "bash" ] || [ "$1" = "php-fpm" ] || [ "$1" = "nginx" ] || [ "$1" = "supervisord" ]; then + exec "$@" +else + exec gosu kool "$@" +fi diff --git a/8.4-debian-nginx-prod/supervisor.conf b/8.4-debian-nginx-prod/supervisor.conf new file mode 100644 index 0000000..35e7cdb --- /dev/null +++ b/8.4-debian-nginx-prod/supervisor.conf @@ -0,0 +1,27 @@ +[supervisord] +logfile=/dev/stdout +logfile_maxbytes=0 +pidfile=/run/supervisord.pid +nodaemon=true + +[program:php-fpm] +command = php-fpm +priority = 10 +autorestart = true +stopasgroup = true +killasgroup = true +stderr_logfile = /dev/stderr +stdout_logfile = /dev/stdout +stderr_logfile_maxbytes = 0 +stdout_logfile_maxbytes = 0 + +[program:nginx] +command = nginx -g "daemon off;" +priority = 20 +autorestart = true +stopasgroup = true +killasgroup = true +stderr_logfile = /dev/stderr +stdout_logfile = /dev/stdout +stderr_logfile_maxbytes = 0 +stdout_logfile_maxbytes = 0 diff --git a/8.4-debian-nginx/Dockerfile b/8.4-debian-nginx/Dockerfile new file mode 100644 index 0000000..ab5fd0a --- /dev/null +++ b/8.4-debian-nginx/Dockerfile @@ -0,0 +1,62 @@ +FROM debian:bookworm AS cert + +WORKDIR /kool/ssl + +RUN apt-get update && \ + apt-get install -y openssl && \ + openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 && \ + openssl rsa -passin pass:x -in server.pass.key -out _.localhost.key && \ + rm server.pass.key && \ + openssl req -new -key _.localhost.key -out server.csr \ + -subj "/C=XX/ST=XX/L=XX/O=Kool-Local/OU=Localhost/CN=*.localhost" && \ + openssl x509 -req -days 365 -in server.csr -signkey _.localhost.key -out _.localhost.crt && \ + openssl x509 -in _.localhost.crt -out _.localhost.pem + +FROM kooldev/php:8.4-debian + +ENV PHP_FPM_LISTEN=/run/php-fpm.sock \ + NGINX_LISTEN=80 \ + NGINX_HTTPS=false \ + NGINX_LISTEN_HTTPS=443 \ + NGINX_HTTPS_CERT=/kool/ssl/_.localhost.pem \ + NGINX_HTTPS_CERT_KEY=/kool/ssl/_.localhost.key \ + NGINX_ROOT=/app/public \ + NGINX_INDEX=index.php \ + NGINX_CLIENT_MAX_BODY_SIZE=25M \ + NGINX_PHP_FPM=unix:/run/php-fpm.sock \ + NGINX_FASTCGI_READ_TIMEOUT=60s \ + NGINX_FASTCGI_BUFFERS='8 8k' \ + NGINX_FASTCGI_BUFFER_SIZE='16k' \ + NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE=true + +RUN apt-get update && apt-get install -y --no-install-recommends supervisor nginx wget \ + && chown -R kool:kool /var/lib/nginx \ + && chmod 770 /var/lib/nginx \ + && ln -sf /dev/stdout /var/log/nginx/access.log \ + && ln -sf /dev/stderr /var/log/nginx/error.log \ + # add h5bp/server-configs-nginx + && mkdir -p /etc/nginx/conf.d \ + && mkdir /etc/nginx/h5bp \ + && cd /etc/nginx/h5bp \ + && wget https://github.com/h5bp/server-configs-nginx/archive/refs/tags/5.0.1.tar.gz -O h5bp.tgz \ + && tar xzvf h5bp.tgz \ + && rm -f h5bp.tgz \ + && mv server-configs-nginx-*/h5bp/* . \ + && mv server-configs-nginx-*/nginx.conf /etc/nginx/nginx.conf \ + && sed -i "s|^user .*|user\ kool kool;|g" /etc/nginx/nginx.conf \ + && mv server-configs-nginx-*/mime.types /etc/nginx/mime.types \ + && rm -rf server-configs-nginx-* \ + && curl -L https://raw.githubusercontent.com/nginxinc/docker-nginx/master/entrypoint/30-tune-worker-processes.sh -o /kool/30-tune-worker-processes.sh \ + && chmod +x /kool/30-tune-worker-processes.sh \ + && apt-get purge -y --auto-remove wget \ + && rm -rf /var/lib/apt/lists/* + +COPY supervisor.conf /kool/supervisor.conf +COPY default.tmpl /kool/default.tmpl +COPY entrypoint /kool/entrypoint +COPY --from=cert /kool/ssl /kool/ssl +RUN chmod +x /kool/entrypoint + +EXPOSE 80 + +CMD [ "supervisord", "-c", "/kool/supervisor.conf" ] diff --git a/8.4-debian-nginx/default.tmpl b/8.4-debian-nginx/default.tmpl new file mode 100644 index 0000000..9992154 --- /dev/null +++ b/8.4-debian-nginx/default.tmpl @@ -0,0 +1,50 @@ +server { + listen {{ .Env.NGINX_LISTEN }} default_server; + server_name _; +{{ if isTrue .Env.NGINX_HTTPS }} + listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; + ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; + ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; +{{ end }} + root {{ .Env.NGINX_ROOT }}; + index {{ .Env.NGINX_INDEX }}; + charset utf-8; + + location = /favicon.ico { log_not_found off; access_log off; } + location = /robots.txt { log_not_found off; access_log off; } + + client_max_body_size {{ .Env.NGINX_CLIENT_MAX_BODY_SIZE }}; + + error_page 404 /index.php; + + location / { + try_files $uri /{{ .Env.NGINX_INDEX }}?$query_string; + } + + location ~ \.php$ { + fastcgi_buffers {{ .Env.NGINX_FASTCGI_BUFFERS }}; + fastcgi_buffer_size {{ .Env.NGINX_FASTCGI_BUFFER_SIZE }}; + fastcgi_pass {{ .Env.NGINX_PHP_FPM }}; + fastcgi_read_timeout {{ .Env.NGINX_FASTCGI_READ_TIMEOUT }}; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.ht { + deny all; + } + + # good practices + add_header X-Frame-Options "SAMEORIGIN"; + + # basic H5BP suggestions + include h5bp/security/referrer-policy.conf; + include h5bp/security/x-content-type-options.conf; + include h5bp/cross-origin/requests.conf; + + # performance enhancements (mostly for caching static data) + include h5bp/web_performance/cache-file-descriptors.conf; + include h5bp/web_performance/compression.conf; +} diff --git a/8.4-debian-nginx/entrypoint b/8.4-debian-nginx/entrypoint new file mode 100644 index 0000000..aeb6633 --- /dev/null +++ b/8.4-debian-nginx/entrypoint @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +if [ "$ENABLE_XDEBUG" = "true" ]; then + if ! docker-php-ext-enable xdebug >> /dev/null 2>&1; then + echo "[ERROR] An error happened enabling xdebug" + exit 1 + fi +fi + +# Run as current user +CURRENT_USER=${ASUSER:-${UID:-0}} + +if [ ! -z "$CURRENT_USER" ] && [ "$CURRENT_USER" != "0" ]; then + usermod -u $CURRENT_USER kool +fi + +dockerize -template /kool/kool.tmpl:/usr/local/etc/php/conf.d/kool.ini -template /kool/zz-docker.tmpl:/usr/local/etc/php-fpm.d/zz-docker.conf -template /kool/default.tmpl:/etc/nginx/conf.d/default.conf + +/kool/30-tune-worker-processes.sh + +# Run entrypoint if provided +if [ ! -z "$ENTRYPOINT" ] && [ -f "$ENTRYPOINT" ]; then + bash $ENTRYPOINT +fi + +if [ "$1" = "sh" ] || [ "$1" = "bash" ] || [ "$1" = "php-fpm" ] || [ "$1" = "nginx" ] || [ "$1" = "supervisord" ]; then + exec "$@" +else + exec gosu kool "$@" +fi diff --git a/8.4-debian-nginx/supervisor.conf b/8.4-debian-nginx/supervisor.conf new file mode 100644 index 0000000..35e7cdb --- /dev/null +++ b/8.4-debian-nginx/supervisor.conf @@ -0,0 +1,27 @@ +[supervisord] +logfile=/dev/stdout +logfile_maxbytes=0 +pidfile=/run/supervisord.pid +nodaemon=true + +[program:php-fpm] +command = php-fpm +priority = 10 +autorestart = true +stopasgroup = true +killasgroup = true +stderr_logfile = /dev/stderr +stdout_logfile = /dev/stdout +stderr_logfile_maxbytes = 0 +stdout_logfile_maxbytes = 0 + +[program:nginx] +command = nginx -g "daemon off;" +priority = 20 +autorestart = true +stopasgroup = true +killasgroup = true +stderr_logfile = /dev/stderr +stdout_logfile = /dev/stdout +stderr_logfile_maxbytes = 0 +stdout_logfile_maxbytes = 0 diff --git a/8.4-debian-prod/Dockerfile b/8.4-debian-prod/Dockerfile new file mode 100644 index 0000000..aeb8927 --- /dev/null +++ b/8.4-debian-prod/Dockerfile @@ -0,0 +1,89 @@ +FROM php:8.4-fpm-bookworm + +ENV ASUSER= \ + UID= \ + COMPOSER_ALLOW_SUPERUSER=1 \ + COMPOSER_MEMORY_LIMIT=-1 \ + PHP_DATE_TIMEZONE=UTC \ + PHP_MEMORY_LIMIT=256M \ + PHP_MAX_INPUT_VARS=1000 \ + PHP_UPLOAD_MAX_FILESIZE=25M \ + PHP_POST_MAX_SIZE=25M \ + PHP_MAX_EXECUTION_TIME=30 \ + PHP_FPM_LISTEN=9000 \ + PHP_FPM_MAX_CHILDREN=10 \ + PHP_FPM_REQUEST_TERMINATE_TIMEOUT=60 \ + ENTRYPOINT=entrypoint.php.sh + +WORKDIR /app + +RUN useradd -m -u 1337 kool \ + && usermod -aG www-data kool \ + # dockerize + && DOCKERIZE_ARCH="$( [ "$(uname -m)" = "aarch64" ] && echo arm64 || echo amd64 )" \ + && curl -L "https://github.com/jwilder/dockerize/releases/download/v0.9.3/dockerize-linux-${DOCKERIZE_ARCH}-v0.9.3.tar.gz" | tar xz \ + && mv dockerize /usr/local/bin/dockerize \ + # gosu + && GOSU_ARCH="$( [ "$(uname -m)" = "aarch64" ] && echo arm64 || echo amd64 )" \ + && curl -L "https://github.com/tianon/gosu/releases/download/1.17/gosu-${GOSU_ARCH}" -o /usr/local/bin/gosu \ + && chmod +x /usr/local/bin/gosu \ + # deps + && apt-get update && apt-get install -y --no-install-recommends \ + bash sed git openssh-client procps \ + libfreetype6 libpng16-16 libjpeg62-turbo libzip4 ghostscript imagemagick \ + jpegoptim optipng pngquant gifsicle \ + libldap-2.5-0 libpq5 libicu72 less \ + # build-deps + && cp "/usr/local/etc/php/php.ini-production" "/usr/local/etc/php/php.ini" \ + && apt-get install -y --no-install-recommends \ + $PHPIZE_DEPS \ + libfreetype6-dev libpng-dev libjpeg62-turbo-dev \ + libicu-dev libedit-dev libxml2-dev \ + libmagickwand-dev libldap2-dev libonig-dev libwebp-dev \ + libpq-dev libzip-dev \ + # php-ext + && docker-php-ext-configure gd --with-freetype --with-webp --with-jpeg \ + && export CFLAGS="$PHP_CFLAGS" CPPFLAGS="$PHP_CPPFLAGS" LDFLAGS="$PHP_LDFLAGS" \ + && docker-php-ext-install -j$(nproc) \ + bcmath \ + calendar \ + exif \ + gd \ + intl \ + ldap \ + mbstring \ + opcache \ + pcntl \ + pdo \ + pdo_mysql \ + pdo_pgsql \ + soap \ + xml \ + zip \ + sockets \ + mysqli \ + ftp \ + && pecl install redis \ + && pecl install imagick \ + && docker-php-ext-enable imagick \ + && docker-php-ext-enable redis \ + # composer + && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ + && curl -sS https://getcomposer.org/installer | php -- --1 --install-dir=/usr/local/bin --filename=composer1 \ + # cleanup + && apt-get purge -y --auto-remove $PHPIZE_DEPS \ + libfreetype6-dev libpng-dev libjpeg62-turbo-dev \ + libicu-dev libedit-dev libxml2-dev \ + libmagickwand-dev libldap2-dev libonig-dev libwebp-dev \ + libpq-dev libzip-dev \ + && rm -rf /var/lib/apt/lists/* /tmp/* + +COPY kool.ini /kool/kool.tmpl +COPY zz-docker.conf /kool/zz-docker.tmpl +COPY entrypoint /kool/entrypoint +RUN chmod +x /kool/entrypoint + +EXPOSE 9000 + +ENTRYPOINT [ "/kool/entrypoint" ] +CMD [ "php-fpm" ] diff --git a/8.4-debian-prod/entrypoint b/8.4-debian-prod/entrypoint new file mode 100644 index 0000000..185cfe8 --- /dev/null +++ b/8.4-debian-prod/entrypoint @@ -0,0 +1,24 @@ +#!/bin/bash +set -e + + +# Run as current user +CURRENT_USER=${ASUSER:-${UID:-0}} + +if [ ! -z "$CURRENT_USER" ] && [ "$CURRENT_USER" != "0" ]; then + usermod -u $CURRENT_USER kool +fi + +dockerize -template /kool/kool.tmpl:/usr/local/etc/php/conf.d/kool.ini -template /kool/zz-docker.tmpl:/usr/local/etc/php-fpm.d/zz-docker.conf + + +# Run entrypoint if provided +if [ ! -z "$ENTRYPOINT" ] && [ -f "$ENTRYPOINT" ]; then + bash $ENTRYPOINT +fi + +if [ "$1" = "sh" ] || [ "$1" = "bash" ] || [ "$1" = "php-fpm" ] ; then + exec "$@" +else + exec gosu kool "$@" +fi diff --git a/8.4-debian-prod/kool.ini b/8.4-debian-prod/kool.ini new file mode 100644 index 0000000..3028217 --- /dev/null +++ b/8.4-debian-prod/kool.ini @@ -0,0 +1,51 @@ +[PHP] + +; Maximum amount of memory a script may consume +; http://php.net/memory-limit +memory_limit = {{ .Env.PHP_MEMORY_LIMIT }} + +; Fix maximum variables per input +max_input_vars = {{ .Env.PHP_MAX_INPUT_VARS }} + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = {{ .Env.PHP_UPLOAD_MAX_FILESIZE }} + +; Maximum size of POST data that PHP will accept. +; Its value may be 0 to disable the limit. It is ignored if POST data reading +; is disabled through enable_post_data_reading. +; http://php.net/post-max-size +post_max_size = {{ .Env.PHP_POST_MAX_SIZE }} + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = {{ .Env.PHP_MAX_EXECUTION_TIME }} + +; Default timezone used by all date/time functions. +; https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone +date.timezone = {{ .Env.PHP_DATE_TIMEZONE }} + + +[opcache] + +; Determines if Zend OPCache is enabled +opcache.enable=1 + +; The OPcache shared memory storage size. +opcache.memory_consumption=512 + +; The amount of memory for interned strings in Mbytes. +opcache.interned_strings_buffer=64 + +; The maximum number of keys (scripts) in the OPcache hash table. +; Only numbers between 200 and 1000000 are allowed. +opcache.max_accelerated_files=30000 + +; When disabled, you must reset the OPcache manually or restart the +; webserver for changes to the filesystem to take effect. +opcache.validate_timestamps=0 + +; If disabled, all PHPDoc comments are dropped from the code to reduce the +; size of the optimized code. +opcache.save_comments=1 diff --git a/8.4-debian-prod/zz-docker.conf b/8.4-debian-prod/zz-docker.conf new file mode 100644 index 0000000..33adb1b --- /dev/null +++ b/8.4-debian-prod/zz-docker.conf @@ -0,0 +1,53 @@ +[global] +daemonize = no + +[www] +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = kool +group = kool + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = {{ .Env.PHP_FPM_LISTEN }} + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. The owner +; and group can be specified either by name or by their numeric IDs. +; Default Values: user and group are set as the running user +; mode is set to 0660 +listen.owner = kool +listen.group = kool + +; Choose how the process manager will control the number of child processes. +; Possible Values: static, dynamic, ondemand (check www.conf for full documentation). +; Note: This value is mandatory. +{{ if or (eq .Env.PHP_FPM_PM "static") (eq .Env.PHP_FPM_PM "dynamic") (eq .Env.PHP_FPM_PM "ondemand") }}pm = {{ .Env.PHP_FPM_PM }}{{ else }}pm = dynamic{{ end }} + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = {{ .Env.PHP_FPM_MAX_CHILDREN }} + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +request_terminate_timeout = {{ .Env.PHP_FPM_REQUEST_TERMINATE_TIMEOUT }} diff --git a/8.4-debian/Dockerfile b/8.4-debian/Dockerfile new file mode 100644 index 0000000..5dd3753 --- /dev/null +++ b/8.4-debian/Dockerfile @@ -0,0 +1,91 @@ +FROM php:8.4-fpm-bookworm + +ENV ASUSER= \ + UID= \ + COMPOSER_ALLOW_SUPERUSER=1 \ + COMPOSER_MEMORY_LIMIT=-1 \ + ENABLE_XDEBUG=false \ + PHP_DATE_TIMEZONE=UTC \ + PHP_MEMORY_LIMIT=256M \ + PHP_MAX_INPUT_VARS=1000 \ + PHP_UPLOAD_MAX_FILESIZE=25M \ + PHP_POST_MAX_SIZE=25M \ + PHP_MAX_EXECUTION_TIME=30 \ + PHP_FPM_LISTEN=9000 \ + PHP_FPM_MAX_CHILDREN=10 \ + PHP_FPM_REQUEST_TERMINATE_TIMEOUT=60 \ + ENTRYPOINT=entrypoint.php.sh + +WORKDIR /app + +RUN useradd -m -u 1337 kool \ + && usermod -aG www-data kool \ + # dockerize + && DOCKERIZE_ARCH="$( [ "$(uname -m)" = "aarch64" ] && echo arm64 || echo amd64 )" \ + && curl -L "https://github.com/jwilder/dockerize/releases/download/v0.9.3/dockerize-linux-${DOCKERIZE_ARCH}-v0.9.3.tar.gz" | tar xz \ + && mv dockerize /usr/local/bin/dockerize \ + # gosu + && GOSU_ARCH="$( [ "$(uname -m)" = "aarch64" ] && echo arm64 || echo amd64 )" \ + && curl -L "https://github.com/tianon/gosu/releases/download/1.17/gosu-${GOSU_ARCH}" -o /usr/local/bin/gosu \ + && chmod +x /usr/local/bin/gosu \ + # deps + && apt-get update && apt-get install -y --no-install-recommends \ + bash sed git openssh-client procps \ + libfreetype6 libpng16-16 libjpeg62-turbo libzip4 ghostscript imagemagick \ + jpegoptim optipng pngquant gifsicle \ + libldap-2.5-0 libpq5 libicu72 less \ + # build-deps + && cp "/usr/local/etc/php/php.ini-development" "/usr/local/etc/php/php.ini" \ + && apt-get install -y --no-install-recommends \ + $PHPIZE_DEPS \ + libfreetype6-dev libpng-dev libjpeg62-turbo-dev \ + libicu-dev libedit-dev libxml2-dev \ + libmagickwand-dev libldap2-dev libonig-dev libwebp-dev \ + libpq-dev libzip-dev \ + # php-ext + && docker-php-ext-configure gd --with-freetype --with-webp --with-jpeg \ + && export CFLAGS="$PHP_CFLAGS" CPPFLAGS="$PHP_CPPFLAGS" LDFLAGS="$PHP_LDFLAGS" \ + && docker-php-ext-install -j$(nproc) \ + bcmath \ + calendar \ + exif \ + gd \ + intl \ + ldap \ + mbstring \ + pcntl \ + pdo \ + pdo_mysql \ + pdo_pgsql \ + soap \ + xml \ + zip \ + sockets \ + mysqli \ + ftp \ + && pecl install redis \ + && pecl install xdebug \ + && pecl install pcov && docker-php-ext-enable pcov \ + && pecl install imagick \ + && docker-php-ext-enable imagick \ + && docker-php-ext-enable redis \ + # composer + && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ + && curl -sS https://getcomposer.org/installer | php -- --1 --install-dir=/usr/local/bin --filename=composer1 \ + # cleanup + && apt-get purge -y --auto-remove $PHPIZE_DEPS \ + libfreetype6-dev libpng-dev libjpeg62-turbo-dev \ + libicu-dev libedit-dev libxml2-dev \ + libmagickwand-dev libldap2-dev libonig-dev libwebp-dev \ + libpq-dev libzip-dev \ + && rm -rf /var/lib/apt/lists/* /tmp/* + +COPY kool.ini /kool/kool.tmpl +COPY zz-docker.conf /kool/zz-docker.tmpl +COPY entrypoint /kool/entrypoint +RUN chmod +x /kool/entrypoint + +EXPOSE 9000 + +ENTRYPOINT [ "/kool/entrypoint" ] +CMD [ "php-fpm" ] diff --git a/8.4-debian/entrypoint b/8.4-debian/entrypoint new file mode 100644 index 0000000..6b17e15 --- /dev/null +++ b/8.4-debian/entrypoint @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +if [ "$ENABLE_XDEBUG" = "true" ]; then + if ! docker-php-ext-enable xdebug >> /dev/null 2>&1; then + echo "[ERROR] An error happened enabling xdebug" + exit 1 + fi +fi + +# Run as current user +CURRENT_USER=${ASUSER:-${UID:-0}} + +if [ ! -z "$CURRENT_USER" ] && [ "$CURRENT_USER" != "0" ]; then + usermod -u $CURRENT_USER kool +fi + +dockerize -template /kool/kool.tmpl:/usr/local/etc/php/conf.d/kool.ini -template /kool/zz-docker.tmpl:/usr/local/etc/php-fpm.d/zz-docker.conf + + +# Run entrypoint if provided +if [ ! -z "$ENTRYPOINT" ] && [ -f "$ENTRYPOINT" ]; then + bash $ENTRYPOINT +fi + +if [ "$1" = "sh" ] || [ "$1" = "bash" ] || [ "$1" = "php-fpm" ] ; then + exec "$@" +else + exec gosu kool "$@" +fi diff --git a/8.4-debian/kool.ini b/8.4-debian/kool.ini new file mode 100644 index 0000000..c671911 --- /dev/null +++ b/8.4-debian/kool.ini @@ -0,0 +1,29 @@ +[PHP] + +; Maximum amount of memory a script may consume +; http://php.net/memory-limit +memory_limit = {{ .Env.PHP_MEMORY_LIMIT }} + +; Fix maximum variables per input +max_input_vars = {{ .Env.PHP_MAX_INPUT_VARS }} + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = {{ .Env.PHP_UPLOAD_MAX_FILESIZE }} + +; Maximum size of POST data that PHP will accept. +; Its value may be 0 to disable the limit. It is ignored if POST data reading +; is disabled through enable_post_data_reading. +; http://php.net/post-max-size +post_max_size = {{ .Env.PHP_POST_MAX_SIZE }} + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = {{ .Env.PHP_MAX_EXECUTION_TIME }} + +; Default timezone used by all date/time functions. +; https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone +date.timezone = {{ .Env.PHP_DATE_TIMEZONE }} + + diff --git a/8.4-debian/zz-docker.conf b/8.4-debian/zz-docker.conf new file mode 100644 index 0000000..33adb1b --- /dev/null +++ b/8.4-debian/zz-docker.conf @@ -0,0 +1,53 @@ +[global] +daemonize = no + +[www] +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = kool +group = kool + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = {{ .Env.PHP_FPM_LISTEN }} + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. The owner +; and group can be specified either by name or by their numeric IDs. +; Default Values: user and group are set as the running user +; mode is set to 0660 +listen.owner = kool +listen.group = kool + +; Choose how the process manager will control the number of child processes. +; Possible Values: static, dynamic, ondemand (check www.conf for full documentation). +; Note: This value is mandatory. +{{ if or (eq .Env.PHP_FPM_PM "static") (eq .Env.PHP_FPM_PM "dynamic") (eq .Env.PHP_FPM_PM "ondemand") }}pm = {{ .Env.PHP_FPM_PM }}{{ else }}pm = dynamic{{ end }} + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = {{ .Env.PHP_FPM_MAX_CHILDREN }} + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +request_terminate_timeout = {{ .Env.PHP_FPM_REQUEST_TERMINATE_TIMEOUT }} diff --git a/8.4-nginx-prod/default.tmpl b/8.4-nginx-prod/default.tmpl index ccafaf3..9992154 100644 --- a/8.4-nginx-prod/default.tmpl +++ b/8.4-nginx-prod/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/8.4-nginx/default.tmpl b/8.4-nginx/default.tmpl index ccafaf3..9992154 100644 --- a/8.4-nginx/default.tmpl +++ b/8.4-nginx/default.tmpl @@ -5,7 +5,7 @@ server { listen {{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate {{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key {{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; {{ end }} root {{ .Env.NGINX_ROOT }}; diff --git a/from-alpine-to-debian.md b/from-alpine-to-debian.md new file mode 100644 index 0000000..7fd0d93 --- /dev/null +++ b/from-alpine-to-debian.md @@ -0,0 +1,152 @@ +# From Alpine to Debian: Migration Guide + +This document outlines the key differences between the Alpine and Debian variants of the kooldev/php Docker images. + +## Quick Comparison + +| Feature | Alpine | Debian | +|---------|--------|--------| +| Base Image | `php:8.x-fpm-alpine` | `php:8.x-fpm-bookworm` (Debian 12 stable) | +| Image Size | Smaller (~150MB) | Larger (~400MB) | +| Package Manager | `apk` | `apt-get` | +| Shell | `sh` (BusyBox) | `bash` | +| Privilege Drop | `su-exec` | `gosu` | +| Supervisord | Python supervisor (Alpine package) | Python supervisor (Debian package) | +| Architecture | amd64 + arm64 | amd64 + arm64 | +| glibc | musl libc | glibc | + +## When to Use Debian + +Choose the Debian variant when: + +- **Compatibility issues with Alpine** - Some PHP extensions or native libraries may have issues with musl libc +- **Debugging needs** - Debian includes more debugging tools out of the box +- **Familiarity** - Teams more familiar with Debian/Ubuntu environments +- **Native library compatibility** - Some C libraries behave differently with glibc vs musl + +## When to Use Alpine + +Choose the Alpine variant when: + +- **Minimal image size is critical** - Alpine images are significantly smaller +- **Security through minimalism** - Smaller attack surface with fewer packages +- **musl libc is acceptable** - Your application has no compatibility issues with musl + +**Note:** Both Alpine and Debian variants now support multi-arch (amd64 + arm64). + +## Key Differences in Detail + +### 1. Supervisord Implementation + +Both **Alpine** and **Debian** now use the official Python-based supervisord package (installed via `apk add supervisor` and `apt-get install supervisor` respectively). The configuration format is identical: + +```ini +# supervisor.conf (both Alpine and Debian) +[supervisord] +logfile=/dev/stdout +logfile_maxbytes=0 +pidfile=/run/supervisord.pid +nodaemon=true + +[program:php-fpm] +command = php-fpm +priority = 10 +autorestart = true +stopasgroup = true +killasgroup = true +stderr_logfile = /dev/stderr +stdout_logfile = /dev/stdout +stderr_logfile_maxbytes = 0 +stdout_logfile_maxbytes = 0 + +[program:nginx] +command = nginx -g "daemon off;" +priority = 20 +autorestart = true +stopasgroup = true +killasgroup = true +stderr_logfile = /dev/stderr +stdout_logfile = /dev/stdout +stderr_logfile_maxbytes = 0 +stdout_logfile_maxbytes = 0 +``` + +**Key configuration points:** +- `priority` controls startup order (lower number starts first) +- `nodaemon=true` keeps supervisord in foreground +- `stdout_logfile_maxbytes=0` disables log rotation for stdout/stderr + +### 2. Entrypoint Script + +**Alpine** uses `sh` shell with `su-exec`: + +```bash +#!/bin/sh +# ... +exec su-exec kool "$@" +``` + +**Debian** uses `bash` with `gosu`: + +```bash +#!/bin/bash +# ... +exec gosu kool "$@" +``` + +### 3. Package Installation + +**Alpine:** +```dockerfile +RUN apk add --no-cache nginx \ + && apk add --no-cache --virtual .build-deps ... \ + && apk del .build-deps +``` + +**Debian:** +```dockerfile +RUN apt-get update \ + && apt-get install -y --no-install-recommends nginx \ + && rm -rf /var/lib/apt/lists/* +``` + +### 4. nginx Directory Structure + +**Alpine:** +```dockerfile +chmod 770 /var/lib/nginx/tmp +``` + +**Debian:** +```dockerfile +chmod 770 /var/lib/nginx +``` + +## Migration Steps + +To migrate from Alpine to Debian: + +1. **Update your image tag:** + ```yaml + # docker-compose.yml + # From: + image: kooldev/php:8.4-nginx + # To: + image: kooldev/php:8.4-debian-nginx + ``` + +2. **Shell scripts:** Update any scripts that use: + - `su-exec` → `gosu` + - BusyBox-specific commands → standard GNU coreutils + - `sh` shebang → `bash` shebang (if using bash features) + +3. **Test thoroughly:** The glibc vs musl difference can cause subtle behavior changes in some applications + +**Note:** Supervisor configuration format is now identical between Alpine and Debian, so no changes needed for custom supervisor configs. + +## Available Debian Image Tags + +- `kooldev/php:8.4-debian` - Base FPM image +- `kooldev/php:8.4-debian-prod` - Production FPM image (no dev tools) +- `kooldev/php:8.4-debian-nginx` - FPM + Nginx with supervisord +- `kooldev/php:8.4-debian-nginx-prod` - Production FPM + Nginx diff --git a/fwd-template.json b/fwd-template.json index 0cbf1e9..323a9b7 100644 --- a/fwd-template.json +++ b/fwd-template.json @@ -484,6 +484,114 @@ "path": "template/Dockerfile-node" } ] + }, + { + "name": "8.4-debian", + "data": { + "from": "php:8.4-fpm-bookworm", + "prod": false, + "nginx": false, + "version": "8.4" + }, + "files": [ + { + "name": "Dockerfile", + "path": "template/Dockerfile-debian" + }, + { + "name": "entrypoint", + "path": "template/entrypoint-debian" + }, + { + "name": "kool.ini", + "path": "template/kool-ini" + }, + { + "name": "zz-docker.conf", + "path": "template/zz-docker-conf" + } + ] + }, + { + "name": "8.4-debian-prod", + "data": { + "from": "php:8.4-fpm-bookworm", + "prod": true, + "nginx": false, + "version": "8.4" + }, + "files": [ + { + "name": "Dockerfile", + "path": "template/Dockerfile-debian" + }, + { + "name": "entrypoint", + "path": "template/entrypoint-debian" + }, + { + "name": "kool.ini", + "path": "template/kool-ini" + }, + { + "name": "zz-docker.conf", + "path": "template/zz-docker-conf" + } + ] + }, + { + "name": "8.4-debian-nginx", + "data": { + "from": "kooldev/php:8.4-debian", + "prod": false, + "nginx": true, + "version": "8.4" + }, + "files": [ + { + "name": "Dockerfile", + "path": "template/Dockerfile-debian-nginx" + }, + { + "name": "entrypoint", + "path": "template/entrypoint-debian" + }, + { + "name": "default.tmpl", + "path": "template/default-tmpl" + }, + { + "name": "supervisor.conf", + "path": "template/supervisor-conf" + } + ] + }, + { + "name": "8.4-debian-nginx-prod", + "data": { + "from": "kooldev/php:8.4-debian-prod", + "prod": true, + "nginx": true, + "version": "8.4" + }, + "files": [ + { + "name": "Dockerfile", + "path": "template/Dockerfile-debian-nginx" + }, + { + "name": "entrypoint", + "path": "template/entrypoint-debian" + }, + { + "name": "default.tmpl", + "path": "template/default-tmpl" + }, + { + "name": "supervisor.conf", + "path": "template/supervisor-conf" + } + ] } ] } diff --git a/kool.yml b/kool.yml index c5d20bb..d262f6a 100644 --- a/kool.yml +++ b/kool.yml @@ -30,6 +30,11 @@ scripts: - docker build -t kooldev/php:8.4-nginx 8.4-nginx - docker build -t kooldev/php:8.4-nginx-prod 8.4-nginx-prod - docker build -t kooldev/php:8.4-node 8.4-node + build-8.4-debian: + - docker build -t kooldev/php:8.4-debian 8.4-debian + - docker build -t kooldev/php:8.4-debian-prod 8.4-debian-prod + - docker build -t kooldev/php:8.4-debian-nginx 8.4-debian-nginx + - docker build -t kooldev/php:8.4-debian-nginx-prod 8.4-debian-nginx-prod build: # parse templates - kool run template @@ -39,3 +44,4 @@ scripts: - kool run build-8.2 - kool run build-8.3 - kool run build-8.4 + - kool run build-8.4-debian diff --git a/tasks/prd-ci-cd-refactor.md b/tasks/prd-ci-cd-refactor.md new file mode 100644 index 0000000..94c1734 --- /dev/null +++ b/tasks/prd-ci-cd-refactor.md @@ -0,0 +1,220 @@ +# PRD: CI/CD GitHub Action Refactor + +## Introduction + +Refactor the CI/CD GitHub Actions workflow to properly handle Docker image build dependencies. The current workflow is broken for Debian images (and potentially fragile for Alpine) because it doesn't correctly handle the dependency between base images and derived images (nginx, node) during multi-architecture builds. + +The core problem: multi-arch builds require the `docker-container` buildx driver, which cannot access locally built images. This means derived images (nginx, node) must pull their base images from Docker Hub, requiring the base images to be pushed first. + +## Goals + +- Enable CI to run on PRs without pushing to Docker Hub (100% local builds) +- Ensure derived images (nginx, node) always build against the locally-built base image during testing +- Support multi-architecture builds (amd64 + arm64) for Docker Hub pushes +- Maintain proper build order: base images must be pushed before derived images +- Preserve all existing test coverage +- Keep downstream repository triggers functional +- Minimize redundant builds (don't rebuild base images unnecessarily) + +## User Stories + +### US-001: Local build and test for PRs ✅ COMPLETED +**Description:** As a contributor, I want PRs to build and test all images locally so I can validate my changes without pushing to Docker Hub. + +**Acceptance Criteria:** +- [x] All builds use `docker` driver (can access local daemon) +- [x] Base images are built and loaded locally first +- [x] Derived images (nginx, node) find base images in local daemon (no Docker Hub pull) +- [x] All tests run against locally built images +- [x] No images are pushed on PR branches +- [x] CI passes for new images that don't exist on Docker Hub yet + +### US-002: Multi-arch push with correct dependency order ✅ COMPLETED +**Description:** As a maintainer, I want master branch pushes to build and push multi-arch images in the correct order so derived images can pull their base from Docker Hub. + +**Acceptance Criteria:** +- [x] Push jobs only run on master branch and correct repository +- [x] Push jobs use `docker-container` driver for multi-arch support +- [x] Base image push jobs complete before derived image push jobs start +- [x] Derived image builds can pull base from Docker Hub (just pushed) +- [x] All images pushed with platforms: linux/amd64,linux/arm64 + +### US-003: Alpine image builds ✅ COMPLETED +**Description:** As a maintainer, I want Alpine images (8.1-8.4, dev and prod variants) to build, test, and push correctly. + +**Acceptance Criteria:** +- [x] Matrix covers versions: 8.1, 8.2, 8.3, 8.4 +- [x] Each version builds both dev and prod variants in same job (no duplicate base builds) +- [x] Base, nginx, and node images all build and test locally per version +- [x] Base images push before nginx/node images (job dependency) +- [x] All existing tests preserved + +### US-004: Debian image builds ✅ COMPLETED +**Description:** As a maintainer, I want Debian images (8.4, dev and prod variants) to build, test, and push correctly. + +**Acceptance Criteria:** +- [x] Matrix covers types: "" (dev), "-prod" +- [x] Version: 8.4 only (for now) +- [x] Base images build and test locally +- [x] Nginx images build and test locally (using local base) +- [x] Base images push before nginx images (job dependency) +- [x] Debian-specific tests preserved (gosu, bash) +- [x] Supervisord test uses correct flag: `supervisord --version` (not `supervisord version`) + +### US-005: Downstream triggers ✅ COMPLETED +**Description:** As a maintainer, I want downstream repositories to be triggered after all images are successfully pushed. + +**Acceptance Criteria:** +- [x] Triggers only run on master branch and correct repository +- [x] Triggers wait for ALL push jobs to complete +- [x] Trigger: kool-dev/docker-wordpress +- [x] Trigger: kool-dev/docker-php-sqlsrv +- [x] Trigger: kool-dev/docker-php-swoole +- [x] Trigger: kool-dev/docker-phpqa + +## Functional Requirements + +### Infrastructure Setup (all jobs) + +- FR-1: All jobs must use `actions/checkout@v4` to get source code +- FR-2: All jobs must use `docker/setup-qemu-action@v3` for multi-arch emulation +- FR-3: All jobs must use `docker/setup-buildx-action@v3` to configure buildx +- FR-4: Push jobs must use `docker/login-action@v3` with Docker Hub credentials (`DOCKER_USERNAME`, `DOCKER_PASSWORD` secrets) +- FR-5: Push jobs must have condition: `if: github.ref == 'refs/heads/master' && github.repository == 'kool-dev/docker-php'` + +### Job Structure + +- FR-6: Create `build-test-alpine` job (matrix: versions 8.1-8.4) that builds and tests ALL images for each version: + - Build base dev → test + - Build base prod → test + - Build nginx dev (uses local base dev) → test + - Build nginx prod (uses local base prod) → test + - Build node (uses local base dev) → test +- FR-7: Create `build-test-debian` job (matrix: types dev/prod) that builds and tests base + nginx locally +- FR-8: Create `push-alpine-base` job (master only, needs: build-test-alpine, matrix: 8.1-8.4 × dev/prod) that pushes base images multi-arch +- FR-9: Create `push-alpine-nginx` job (master only, needs: push-alpine-base, matrix: 8.1-8.4 × dev/prod) that pushes nginx images multi-arch +- FR-10: Create `push-alpine-node` job (master only, needs: push-alpine-base, matrix: 8.1-8.4) that pushes node images multi-arch +- FR-11: Create `push-debian-base` job (master only, needs: build-test-debian, matrix: dev/prod) that pushes base images multi-arch +- FR-12: Create `push-debian-nginx` job (master only, needs: push-debian-base, matrix: dev/prod) that pushes nginx images multi-arch +- FR-13: Create trigger jobs (master only, needs: all push jobs) for downstream repositories + +### Build Configuration + +- FR-14: Test jobs must use `docker` buildx driver with `driver: docker` (enables local image access) +- FR-15: Push jobs must use default `docker-container` buildx driver (enables multi-arch) +- FR-16: Test jobs must use `load: true` to load images into local daemon +- FR-17: Push jobs must use `push: true` and `platforms: linux/amd64,linux/arm64` +- FR-18: Push jobs must NOT use `load: true` (incompatible with multi-platform) + +### Tests to Preserve + +- FR-19: Basic tests: `php -v`, `composer -V`, `composer1 -V`, ASUSER user switching, readline module +- FR-20: Dockerize tests: version check, template rendering with environment variable +- FR-21: PHP extension tests: bcmath, gd, intl, pdo_mysql, pdo_pgsql, redis, zip, mbstring, ldap +- FR-22: Production tests: OPcache enabled, xdebug NOT loadable even with ENABLE_XDEBUG=true +- FR-23: Development tests: pcov available, xdebug loadable with ENABLE_XDEBUG=true +- FR-24: Nginx tests: `nginx -v`, `nginx -T`, `supervisord --version` +- FR-25: Node tests: `node -v`, `npm -v`, `yarn -v` +- FR-26: Debian-specific tests: `gosu --version`, uid switching test with ASUSER + +## Non-Goals + +- No changes to Dockerfile content (only CI/CD workflow) +- No changes to image tags or naming conventions +- No support for pushing from PR branches +- No build caching strategy (can be added in future PR) +- No changes to the template system (blade templates) + +## Technical Considerations + +### Buildx Driver Behavior + +| Driver | Local Images | Multi-arch | Use Case | +|--------|--------------|------------|----------| +| `docker` | Yes (daemon access) | No | Local build + test | +| `docker-container` | No (isolated) | Yes | Multi-arch push | + +### Job Dependencies (master branch) + +``` +build-test-alpine ──────► push-alpine-base ─────┬──► push-alpine-nginx + (4 jobs) (8 jobs) │ (8 jobs) + │ + └──► push-alpine-node + (4 jobs) + +build-test-debian ──────► push-debian-base ─────────► push-debian-nginx + (2 jobs) (2 jobs) (2 jobs) + +All push jobs ──────────► trigger-wordpress + trigger-extended +``` + +**Note on matrix dependencies:** When `push-alpine-nginx` depends on `push-alpine-base`, GitHub Actions waits for ALL matrix entries of push-alpine-base to complete before starting ANY matrix entry of push-alpine-nginx. This is a GitHub Actions limitation (no per-matrix-entry dependencies). This is acceptable as it guarantees all base images are available. + +### Matrix Definitions + +**Alpine test (consolidated - one job per version):** +```yaml +matrix: + version: ["8.1", "8.2", "8.3", "8.4"] +# Each job builds: base dev, base prod, nginx dev, nginx prod, node +``` + +**Alpine base push:** +```yaml +matrix: + version: ["8.1", "8.2", "8.3", "8.4"] + type: ["", "-prod"] +``` + +**Alpine nginx push:** +```yaml +matrix: + version: ["8.1", "8.2", "8.3", "8.4"] + type: ["", "-prod"] +``` + +**Alpine node push:** +```yaml +matrix: + version: ["8.1", "8.2", "8.3", "8.4"] +# Node only has dev variant (no -prod) +``` + +**Debian test:** +```yaml +matrix: + type: ["", "-prod"] +# Version fixed at 8.4 +``` + +**Debian base/nginx push:** +```yaml +matrix: + type: ["", "-prod"] +# Version fixed at 8.4 +``` + +### Build Overhead + +Each image gets built multiple times: +1. **Test job:** Single-arch local build (fast, for testing) +2. **Push job:** Multi-arch rebuild (slower, for production) + +This is unavoidable because the `docker-container` driver (required for multi-arch) cannot access locally built images. Build caching can mitigate this in a future PR. + +## Success Metrics + +- CI passes on the debian branch (currently broken) +- CI passes for PRs without any Docker Hub access +- All 4 Debian images successfully pushed to Docker Hub from master +- All Alpine images continue to work as before +- Downstream triggers fire successfully after pushes complete +- No duplicate base image builds within test jobs (consolidated approach) + +## Open Questions + +- Should we add build caching to speed up CI? (deferred to future PR) +- Should Debian support more PHP versions (8.1-8.3)? (out of scope for this PR) +- Should we add a "dry-run" push option for testing? (out of scope) diff --git a/template/Dockerfile-debian-nginx.blade.php b/template/Dockerfile-debian-nginx.blade.php new file mode 100644 index 0000000..3cd2ca9 --- /dev/null +++ b/template/Dockerfile-debian-nginx.blade.php @@ -0,0 +1,62 @@ +FROM debian:bookworm AS cert + +WORKDIR /kool/ssl + +RUN apt-get update && \ + apt-get install -y openssl && \ + openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 && \ + openssl rsa -passin pass:x -in server.pass.key -out _.localhost.key && \ + rm server.pass.key && \ + openssl req -new -key _.localhost.key -out server.csr \ + -subj "/C=XX/ST=XX/L=XX/O=Kool-Local/OU=Localhost/CN=*.localhost" && \ + openssl x509 -req -days 365 -in server.csr -signkey _.localhost.key -out _.localhost.crt && \ + openssl x509 -in _.localhost.crt -out _.localhost.pem + +FROM {{ $from }} + +ENV PHP_FPM_LISTEN=/run/php-fpm.sock \ + NGINX_LISTEN=80 \ + NGINX_HTTPS=false \ + NGINX_LISTEN_HTTPS=443 \ + NGINX_HTTPS_CERT=/kool/ssl/_.localhost.pem \ + NGINX_HTTPS_CERT_KEY=/kool/ssl/_.localhost.key \ + NGINX_ROOT=/app/public \ + NGINX_INDEX=index.php \ + NGINX_CLIENT_MAX_BODY_SIZE=25M \ + NGINX_PHP_FPM=unix:/run/php-fpm.sock \ + NGINX_FASTCGI_READ_TIMEOUT=60s \ + NGINX_FASTCGI_BUFFERS='8 8k' \ + NGINX_FASTCGI_BUFFER_SIZE='16k' \ + NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE=true + +RUN apt-get update && apt-get install -y --no-install-recommends supervisor nginx wget \ + && chown -R kool:kool /var/lib/nginx \ + && chmod 770 /var/lib/nginx \ + && ln -sf /dev/stdout /var/log/nginx/access.log \ + && ln -sf /dev/stderr /var/log/nginx/error.log \ + # add h5bp/server-configs-nginx + && mkdir -p /etc/nginx/conf.d \ + && mkdir /etc/nginx/h5bp \ + && cd /etc/nginx/h5bp \ + && wget https://github.com/h5bp/server-configs-nginx/archive/refs/tags/5.0.1.tar.gz -O h5bp.tgz \ + && tar xzvf h5bp.tgz \ + && rm -f h5bp.tgz \ + && mv server-configs-nginx-*/h5bp/* . \ + && mv server-configs-nginx-*/nginx.conf /etc/nginx/nginx.conf \ + && sed -i "s|^user .*|user\ kool kool;|g" /etc/nginx/nginx.conf \ + && mv server-configs-nginx-*/mime.types /etc/nginx/mime.types \ + && rm -rf server-configs-nginx-* \ + && curl -L https://raw.githubusercontent.com/nginxinc/docker-nginx/master/entrypoint/30-tune-worker-processes.sh -o /kool/30-tune-worker-processes.sh \ + && chmod +x /kool/30-tune-worker-processes.sh \ + && apt-get purge -y --auto-remove wget \ + && rm -rf /var/lib/apt/lists/* + +COPY supervisor.conf /kool/supervisor.conf +COPY default.tmpl /kool/default.tmpl +COPY entrypoint /kool/entrypoint +COPY --from=cert /kool/ssl /kool/ssl +RUN chmod +x /kool/entrypoint + +EXPOSE 80 + +CMD [ "supervisord", "-c", "/kool/supervisor.conf" ] diff --git a/template/Dockerfile-debian.blade.php b/template/Dockerfile-debian.blade.php new file mode 100644 index 0000000..9f3bae7 --- /dev/null +++ b/template/Dockerfile-debian.blade.php @@ -0,0 +1,98 @@ +FROM {{ $from }} + +ENV ASUSER= \ + UID= \ + COMPOSER_ALLOW_SUPERUSER=1 \ + COMPOSER_MEMORY_LIMIT=-1 \ +@unless ($prod) + ENABLE_XDEBUG=false \ +@endunless + PHP_DATE_TIMEZONE=UTC \ + PHP_MEMORY_LIMIT=256M \ + PHP_MAX_INPUT_VARS=1000 \ + PHP_UPLOAD_MAX_FILESIZE=25M \ + PHP_POST_MAX_SIZE=25M \ + PHP_MAX_EXECUTION_TIME=30 \ + PHP_FPM_LISTEN=9000 \ + PHP_FPM_MAX_CHILDREN=10 \ + PHP_FPM_REQUEST_TERMINATE_TIMEOUT=60 \ + ENTRYPOINT=entrypoint.php.sh + +WORKDIR /app + +RUN useradd -m -u 1337 kool \ + && usermod -aG www-data kool \ + # dockerize + && DOCKERIZE_ARCH="$( [ "$(uname -m)" = "aarch64" ] && echo arm64 || echo amd64 )" \ + && curl -L "https://github.com/jwilder/dockerize/releases/download/v0.9.3/dockerize-linux-${DOCKERIZE_ARCH}-v0.9.3.tar.gz" | tar xz \ + && mv dockerize /usr/local/bin/dockerize \ + # gosu + && GOSU_ARCH="$( [ "$(uname -m)" = "aarch64" ] && echo arm64 || echo amd64 )" \ + && curl -L "https://github.com/tianon/gosu/releases/download/1.17/gosu-${GOSU_ARCH}" -o /usr/local/bin/gosu \ + && chmod +x /usr/local/bin/gosu \ + # deps + && apt-get update && apt-get install -y --no-install-recommends \ + bash sed git openssh-client procps \ + libfreetype6 libpng16-16 libjpeg62-turbo libzip4 ghostscript imagemagick \ + jpegoptim optipng pngquant gifsicle \ + libldap-2.5-0 libpq5 libicu72 less \ + # build-deps + && cp "/usr/local/etc/php/php.ini-{{ $prod ? 'production' : 'development' }}" "/usr/local/etc/php/php.ini" \ + && apt-get install -y --no-install-recommends \ + $PHPIZE_DEPS \ + libfreetype6-dev libpng-dev libjpeg62-turbo-dev \ + libicu-dev libedit-dev libxml2-dev \ + libmagickwand-dev libldap2-dev libonig-dev libwebp-dev \ + libpq-dev libzip-dev \ + # php-ext + && docker-php-ext-configure gd --with-freetype --with-webp --with-jpeg \ + && export CFLAGS="$PHP_CFLAGS" CPPFLAGS="$PHP_CPPFLAGS" LDFLAGS="$PHP_LDFLAGS" \ + && docker-php-ext-install -j$(nproc) \ + bcmath \ + calendar \ + exif \ + gd \ + intl \ + ldap \ + mbstring \ +@if ($prod) + opcache \ +@endif + pcntl \ + pdo \ + pdo_mysql \ + pdo_pgsql \ + soap \ + xml \ + zip \ + sockets \ + mysqli \ + ftp \ + && pecl install redis \ +@if (! $prod) + && pecl install xdebug \ + && pecl install pcov && docker-php-ext-enable pcov \ +@endif + && pecl install imagick \ + && docker-php-ext-enable imagick \ + && docker-php-ext-enable redis \ + # composer + && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ + && curl -sS https://getcomposer.org/installer | php -- --1 --install-dir=/usr/local/bin --filename=composer1 \ + # cleanup + && apt-get purge -y --auto-remove $PHPIZE_DEPS \ + libfreetype6-dev libpng-dev libjpeg62-turbo-dev \ + libicu-dev libedit-dev libxml2-dev \ + libmagickwand-dev libldap2-dev libonig-dev libwebp-dev \ + libpq-dev libzip-dev \ + && rm -rf /var/lib/apt/lists/* /tmp/* + +COPY kool.ini /kool/kool.tmpl +COPY zz-docker.conf /kool/zz-docker.tmpl +COPY entrypoint /kool/entrypoint +RUN chmod +x /kool/entrypoint + +EXPOSE 9000 + +ENTRYPOINT [ "/kool/entrypoint" ] +CMD [ "php-fpm" ] diff --git a/template/default-tmpl.blade.php b/template/default-tmpl.blade.php index 177d0b3..caf8a2e 100644 --- a/template/default-tmpl.blade.php +++ b/template/default-tmpl.blade.php @@ -5,7 +5,7 @@ listen @{{ .Env.NGINX_LISTEN_HTTPS }} ssl http2; ssl_certificate @{{ .Env.NGINX_HTTPS_CERT }}; ssl_certificate_key @{{ .Env.NGINX_HTTPS_CERT_KEY }}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; @{{ end }} root @{{ .Env.NGINX_ROOT }}; diff --git a/template/entrypoint-debian.blade.php b/template/entrypoint-debian.blade.php new file mode 100644 index 0000000..a5cf2f1 --- /dev/null +++ b/template/entrypoint-debian.blade.php @@ -0,0 +1,35 @@ +#!/bin/bash +set -e + +@unless ($prod) +if [ "$ENABLE_XDEBUG" = "true" ]; then + if ! docker-php-ext-enable xdebug >> /dev/null 2>&1; then + echo "[ERROR] An error happened enabling xdebug" + exit 1 + fi +fi +@endunless + +# Run as current user +CURRENT_USER=${ASUSER:-${UID:-0}} + +if [ ! -z "$CURRENT_USER" ] && [ "$CURRENT_USER" != "0" ]; then + usermod -u $CURRENT_USER kool +fi + +dockerize -template /kool/kool.tmpl:/usr/local/etc/php/conf.d/kool.ini -template /kool/zz-docker.tmpl:/usr/local/etc/php-fpm.d/zz-docker.conf {!! $nginx ? '-template /kool/default.tmpl:/etc/nginx/conf.d/default.conf' : '' !!} + +@if ($nginx) +/kool/30-tune-worker-processes.sh +@endif + +# Run entrypoint if provided +if [ ! -z "$ENTRYPOINT" ] && [ -f "$ENTRYPOINT" ]; then + bash $ENTRYPOINT +fi + +if [ "$1" = "sh" ] || [ "$1" = "bash" ] || [ "$1" = "php-fpm" ] {!! $nginx ? '|| [ "$1" = "nginx" ] || [ "$1" = "supervisord" ]' : '' !!}; then + exec "$@" +else + exec gosu kool "$@" +fi