Compare commits

...
15 Commits
Author SHA1 Message Date
jkaninda eb1e00e45e Merge pull request #97 from jkaninda/dev
Build / docker (8.2, alpine) (push) Canceled after 0s
Build / docker (8.2, debian) (push) Canceled after 0s
Build / docker (8.3, alpine) (push) Canceled after 0s
Build / docker (8.3, debian) (push) Canceled after 0s
Build / docker (8.4, alpine) (push) Canceled after 0s
Build / docker (8.4, debian) (push) Canceled after 0s
Build / docker (8.5, alpine) (push) Canceled after 0s
Build / docker (8.5, debian) (push) Canceled after 0s
Build / legacy (./src/docker/7.2/Dockerfile, 7.2, linux/amd64, 7.2) (push) Canceled after 0s
Build / legacy (./src/docker/7.3/Dockerfile, 7.3, linux/amd64, 7.3) (push) Canceled after 0s
Build / legacy (./src/docker/7.4/Dockerfile, 7.4, linux/amd64, 7.4) (push) Canceled after 0s
Build / legacy (./src/docker/8.0/Dockerfile, 8.0, linux/amd64, 8.0) (push) Canceled after 0s
Build / legacy (./src/docker/Dockerfile, 8.1, linux/amd64,linux/arm64, 8.1) (push) Canceled after 0s
Build / legacy (./src/docker/Dockerfile.alpine, 8.1, linux/amd64,linux/arm64, 8.1-alpine) (push) Canceled after 0s
Tests / integration (8.2, alpine) (push) Canceled after 0s
Tests / integration (8.2, debian) (push) Canceled after 0s
Tests / integration (8.3, alpine) (push) Canceled after 0s
Tests / integration (8.3, debian) (push) Canceled after 0s
Tests / integration (8.4, alpine) (push) Canceled after 0s
Tests / integration (8.4, debian) (push) Canceled after 0s
Tests / integration (8.5, alpine) (push) Canceled after 0s
Tests / integration (8.5, debian) (push) Canceled after 0s
Move PHP 8.1 to legacy images
2026-10-22 05:24:43 +02:00
jkaninda 915b7709de Move PHP 8.1 to legacy images
Tests / integration (8.2, alpine) (push) Canceled after 0s
Tests / integration (8.2, debian) (push) Canceled after 0s
Tests / integration (8.3, alpine) (push) Canceled after 0s
Tests / integration (8.3, debian) (push) Canceled after 0s
Tests / integration (8.4, alpine) (push) Canceled after 0s
Tests / integration (8.4, debian) (push) Canceled after 0s
Tests / integration (8.5, alpine) (push) Canceled after 0s
Tests / integration (8.5, debian) (push) Canceled after 0s
PHP 8.1 is end-of-life. Drop it from the default build and test
matrices. 8.1 and 8.1-alpine are still built, multi-arch, by the manual
legacy job (workflow_dispatch with legacy=true)
2026-10-22 05:20:16 +02:00
jkaninda 8471b194b6 Merge pull request #92 from jkaninda/dependabot/github_actions/docker/build-push-action-7
Bump docker/build-push-action from 6 to 7
2026-10-22 05:14:23 +02:00
jkaninda 131ce481ba Make PECL installs fail-fast with retries; harden integration test (#96)
* Make PECL installs fail-fast with retries; harden integration test
2026-10-22 00:04:29 +02:00
dependabot[bot] 2c0dfa1145 Bump docker/build-push-action from 6 to 7
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-21 21:05:52 +00:00
jkaninda 16f5e551d2 Merge pull request #93 from jkaninda/dependabot/github_actions/docker/setup-qemu-action-4
Build / docker (8.1, alpine) (push) Canceled after 0s
Build / docker (8.1, debian) (push) Canceled after 0s
Build / docker (8.2, alpine) (push) Canceled after 0s
Build / docker (8.2, debian) (push) Canceled after 0s
Build / docker (8.3, alpine) (push) Canceled after 0s
Build / docker (8.3, debian) (push) Canceled after 0s
Build / docker (8.4, alpine) (push) Canceled after 0s
Build / docker (8.4, debian) (push) Canceled after 0s
Build / docker (8.5, alpine) (push) Canceled after 0s
Build / docker (8.5, debian) (push) Canceled after 0s
Build / legacy (7.2) (push) Canceled after 0s
Build / legacy (7.3) (push) Canceled after 0s
Build / legacy (7.4) (push) Canceled after 0s
Tests / integration (8.3, debian) (push) Canceled after 0s
Build / legacy (8.0) (push) Canceled after 0s
Tests / integration (8.1, alpine) (push) Canceled after 0s
Tests / integration (8.1, debian) (push) Canceled after 0s
Tests / integration (8.2, alpine) (push) Canceled after 0s
Tests / integration (8.2, debian) (push) Canceled after 0s
Tests / integration (8.3, alpine) (push) Canceled after 0s
Tests / integration (8.4, alpine) (push) Canceled after 0s
Tests / integration (8.4, debian) (push) Canceled after 0s
Tests / integration (8.5, alpine) (push) Canceled after 0s
Tests / integration (8.5, debian) (push) Canceled after 0s
Bump docker/setup-qemu-action from 3 to 4
2026-10-21 23:03:49 +02:00
jkaninda ccf31fcc83 Merge pull request #94 from jkaninda/dependabot/github_actions/docker/setup-buildx-action-4
Bump docker/setup-buildx-action from 3 to 4
2026-10-21 23:03:20 +02:00
jkaninda 617d7acd77 Merge pull request #95 from jkaninda/dependabot/github_actions/actions/checkout-7
Bump actions/checkout from 5 to 7
2026-10-21 23:03:06 +02:00
jkaninda 80649e5ae8 Merge pull request #91 from jkaninda/dependabot/github_actions/docker/login-action-4
Bump docker/login-action from 3 to 4
2026-10-21 23:02:50 +02:00
dependabot[bot] 03020a04d2 Bump actions/checkout from 5 to 7
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-21 18:56:51 +00:00
dependabot[bot] d1ca56b820 Bump docker/setup-buildx-action from 3 to 4
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-21 18:56:48 +00:00
dependabot[bot] 8adcc92c9f Bump docker/setup-qemu-action from 3 to 4
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-21 18:56:42 +00:00
dependabot[bot] 64e61d40cd Bump docker/login-action from 3 to 4
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-21 18:56:29 +00:00
jkaninda 7799d2fbc2 Merge pull request #90 from jkaninda/dev
Upgrade images to PHP 8.5 and fix php-fpm not starting as root
2026-10-21 20:53:47 +02:00
jkaninda 033c6b213f Merge pull request #88 from jkaninda/docs
Build / docker (push) Has been cancelled
Tests / integration (push) Has been cancelled
update readme
2025-07-27 07:25:53 +02:00
23 changed files with 713 additions and 526 deletions

No files matched your search

Vendored
BIN
View File
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
+81 -90
View File
@@ -3,105 +3,96 @@ on:
push: push:
branches: branches:
- master - master
workflow_dispatch:
inputs:
legacy:
description: 'Also build legacy images (7.2, 7.3, 7.4, 8.0, 8.1)'
required: false
default: false
type: boolean
env:
LATEST_PHP: "8.5"
jobs: jobs:
docker: docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ["8.2", "8.3", "8.4", "8.5"]
variant: ["debian", "alpine"]
steps: steps:
- - uses: actions/checkout@v7
name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v4
- - name: Set up Docker Buildx
name: Set up Docker Buildx uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v2 - name: Login to DockerHub
- uses: docker/login-action@v4
name: Login to DockerHub
uses: docker/login-action@v2
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Compute tags
name: Build and push 8.1 id: meta
uses: docker/build-push-action@v3 run: |
image="${{ vars.BUILDKIT_IMAGE }}"
if [ "${{ matrix.variant }}" = "alpine" ]; then
file=./src/docker/Dockerfile.alpine
tags="${image}:${{ matrix.php }}-alpine"
[ "${{ matrix.php }}" = "${LATEST_PHP}" ] && tags="${tags},${image}:alpine"
else
file=./src/docker/Dockerfile
tags="${image}:${{ matrix.php }}"
[ "${{ matrix.php }}" = "${LATEST_PHP}" ] && tags="${tags},${image}:latest"
fi
echo "file=${file}" >> "$GITHUB_OUTPUT"
echo "tags=${tags}" >> "$GITHUB_OUTPUT"
- name: Build and push ${{ matrix.php }} ${{ matrix.variant }}
uses: docker/build-push-action@v7
with: with:
file: "./src/docker/Dockerfile" context: .
file: ${{ steps.meta.outputs.file }}
push: true push: true
pull: true
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
build-args: | build-args: |
phpVersion=8.1 phpVersion=${{ matrix.php }}
tags: "${{ vars.BUILDKIT_IMAGE }}:8.1" tags: ${{ steps.meta.outputs.tags }}
- cache-from: type=gha,scope=${{ matrix.php }}-${{ matrix.variant }}
name: Build and push 8.1 alpine cache-to: type=gha,mode=max,scope=${{ matrix.php }}-${{ matrix.variant }}
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.1
tags: "${{ vars.BUILDKIT_IMAGE }}:8.1-alpine"
-
name: Build and push 8.2
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.2
tags: "${{vars.BUILDKIT_IMAGE}}:8.2"
-
name: Build and push 8.2 alpine
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.2
tags: "${{vars.BUILDKIT_IMAGE}}:8.2-alpine"
-
name: Build and push 8.3
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.3
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.3"
-
name: Build and push 8.3 alpine
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.3
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.3-alpine"
-
name: Build and push 8.4 alpine
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.4
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.4-alpine"
-
name: Build and push 8.4
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.4
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.4"
"${{vars.BUILDKIT_IMAGE}}:latest"
legacy:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.legacy }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- { tag: "7.2", phpVersion: "7.2", file: ./src/docker/7.2/Dockerfile, platforms: linux/amd64 }
- { tag: "7.3", phpVersion: "7.3", file: ./src/docker/7.3/Dockerfile, platforms: linux/amd64 }
- { tag: "7.4", phpVersion: "7.4", file: ./src/docker/7.4/Dockerfile, platforms: linux/amd64 }
- { tag: "8.0", phpVersion: "8.0", file: ./src/docker/8.0/Dockerfile, platforms: linux/amd64 }
- { tag: "8.1", phpVersion: "8.1", file: ./src/docker/Dockerfile, platforms: "linux/amd64,linux/arm64" }
- { tag: "8.1-alpine", phpVersion: "8.1", file: ./src/docker/Dockerfile.alpine, platforms: "linux/amd64,linux/arm64" }
steps:
- uses: actions/checkout@v7
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to DockerHub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push ${{ matrix.tag }}
uses: docker/build-push-action@v7
with:
context: .
file: ${{ matrix.file }}
push: true
platforms: ${{ matrix.platforms }}
build-args: |
phpVersion=${{ matrix.phpVersion }}
tags: ${{ vars.BUILDKIT_IMAGE }}:${{ matrix.tag }}
-138
View File
@@ -1,138 +0,0 @@
name: Manual-build
on:
workflow_dispatch:
inputs:
docker_tag:
description: 'Docker tag'
required: true
default: 'latest'
type: string
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push 7.2
uses: docker/build-push-action@v3
with:
file: "./src/docker/7.2/Dockerfile"
push: true
tags: "${{vars.BUILDKIT_IMAGE}}:7.2"
-
name: Build and push 7.3
uses: docker/build-push-action@v3
with:
file: "./src/docker/7.3/Dockerfile"
push: true
tags: "${{vars.BUILDKIT_IMAGE}}:7.3"
-
name: Build and push 7.4
uses: docker/build-push-action@v3
with:
file: "./src/docker/7.4/Dockerfile"
push: true
tags: "${{vars.BUILDKIT_IMAGE}}:7.4"
-
name: Build and push 8.0
uses: docker/build-push-action@v3
with:
file: "./src/docker/8.0/Dockerfile"
push: true
tags: "${{vars.BUILDKIT_IMAGE}}:8.0"
-
name: Build and push 8.1
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.1
tags: "${{ vars.BUILDKIT_IMAGE }}:8.1"
-
name: Build and push 8.1 alpine
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.1
tags: "${{ vars.BUILDKIT_IMAGE }}:8.1-alpine"
-
name: Build and push 8.2
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.2
tags: "${{vars.BUILDKIT_IMAGE}}:8.2"
-
name: Build and push 8.2 alpine
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.2
tags: "${{vars.BUILDKIT_IMAGE}}:8.2-alpine"
-
name: Build and push 8.3
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.3
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.3"
-
name: Build and push 8.3 alpine
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.3
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.3-alpine"
-
name: Build and push 8.4 alpine
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile.alpine"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.4
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.4-alpine"
-
name: Build and push 8.4
uses: docker/build-push-action@v3
with:
file: "./src/docker/Dockerfile"
push: true
platforms: linux/amd64,linux/arm64
build-args: |
phpVersion=8.4
tags: |
"${{vars.BUILDKIT_IMAGE}}:8.4"
"${{vars.BUILDKIT_IMAGE}}:latest"
+24 -46
View File
@@ -1,53 +1,31 @@
name: Tests name: Tests
on: on:
push: push:
pull_request:
jobs: jobs:
integration: integration:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ["8.2", "8.3", "8.4", "8.5"]
variant: ["debian", "alpine"]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v7
- name: Build Docker Image - name: Set up Docker Buildx
run: | uses: docker/setup-buildx-action@v4
docker buildx build -f src/docker/Dockerfile --build-arg phpVersion=8.4 -t ${{ vars.BUILDKIT_IMAGE }}:latest --load . - name: Build Docker image
- name: Verify Docker images uses: docker/build-push-action@v7
run: | with:
docker images context: .
- name: Create Laravel project file: ${{ matrix.variant == 'alpine' && './src/docker/Dockerfile.alpine' || './src/docker/Dockerfile' }}
run: | load: true
composer create-project laravel/laravel laravel build-args: |
- name: Fix Permission phpVersion=${{ matrix.php }}
run: chmod -R 777 ./laravel/storage tags: laravel-php-fpm:test
- name: Run docker-compose cache-from: type=gha,scope=${{ matrix.php }}-${{ matrix.variant }}
run: - name: Run integration tests
cp ./tests/compose.yaml compose.yaml && env:
docker compose -f "compose.yaml" up -d IMAGE: laravel-php-fpm:test
- name: Create script.js for K6 test run: ./tests/integration.sh
run: |
touch script.js && cat > script.js <<EOF
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
//Link
http.get('http://localhost');
}
EOF
- name: Install k6
run: |
curl https://github.com/grafana/k6/releases/download/v0.47.0/k6-v0.47.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1
- name: Test with K6
run: |
./k6 run script.js
- name: Test with curl
run: |
curl -i http://localhost
- name: Waiting for database connection
run: |
while ! docker exec mysql mysql --user=root --password=password -e "status" &> /dev/null ; do
echo "Waiting for database connection..."
sleep 5
done
- name: Laravel database migration test
run: |
docker exec php-fpm php artisan migrate
+4 -1
View File
@@ -1,3 +1,6 @@
.DS_Store
/.history /.history
laravel laravel
docker-compose.yml docker-compose.yml
.DS_Store
tests/modules.txt
+36 -22
View File
@@ -1,27 +1,41 @@
IMAGE_NAME?=jkaninda/laravel-php-fpm IMAGE_NAME?=jkaninda/laravel-php-fpm
PHP_VERSIONS?=8.2 8.3 8.4 8.5
LATEST_PHP?=8.5
.PHONY: all .PHONY: all
all: build all: build
##@ Build ##@ Build
.PHONY: build .PHONY: build
build: build-81 build-82 build-83 build-84 build: $(addprefix build-,$(PHP_VERSIONS))
.PHONY: build-80
build-80: .PHONY: build-alpine
docker build --build-arg phpVersion=8.0 -f src/docker/8.0/Dockerfile -t ${IMAGE_NAME}:8.0 . build-alpine: $(addsuffix -alpine,$(addprefix build-,$(PHP_VERSIONS)))
.PHONY: build-81
build-81: .PHONY: build-latest
docker build --build-arg phpVersion=8.1 -f src/docker/Dockerfile -t ${IMAGE_NAME}:8.1 . build-latest: build-$(LATEST_PHP) build-$(LATEST_PHP)-alpine
.PHONY: build-82 docker tag ${IMAGE_NAME}:$(LATEST_PHP) ${IMAGE_NAME}:latest
build-82: docker tag ${IMAGE_NAME}:$(LATEST_PHP)-alpine ${IMAGE_NAME}:alpine
docker build --build-arg phpVersion=8.2 -f src/docker/Dockerfile -t ${IMAGE_NAME}:8.2 .
.PHONY: build-83 # Legacy images (7.2, 7.3, 7.4, 8.0). PHP 8.1 is legacy too but uses the
build-83: # shared Dockerfiles: make build-8.1 / make build-8.1-alpine
docker build --build-arg phpVersion=8.3 -f src/docker/Dockerfile -t ${IMAGE_NAME}:8.3 . .PHONY: build-7.2 build-7.3 build-7.4 build-8.0
.PHONY: build-84 build-7.2 build-7.3 build-7.4 build-8.0: build-%:
build-84: docker build -f src/docker/$*/Dockerfile -t ${IMAGE_NAME}:$* .
docker build --build-arg phpVersion=8.4 -f src/docker/Dockerfile -t ${IMAGE_NAME}:8.4 .
.PHONY: build-81-alpine .PHONY: build-%-alpine
build-81-alpine: build-%-alpine:
docker build --build-arg phpVersion=8.1 -f src/docker/Dockerfile.alpine -t ${IMAGE_NAME}:8.1-alpine . docker build --build-arg phpVersion=$* -f src/docker/Dockerfile.alpine -t ${IMAGE_NAME}:$*-alpine .
.PHONY: build-84-alpine
build-84-alpine: .PHONY: build-%
docker build --build-arg phpVersion=8.4 -f src/docker/Dockerfile.alpine -t ${IMAGE_NAME}:8.4-alpine . build-%:
docker build --build-arg phpVersion=$* -f src/docker/Dockerfile -t ${IMAGE_NAME}:$* .
##@ Test
.PHONY: test
test: build-$(LATEST_PHP)
IMAGE=${IMAGE_NAME}:$(LATEST_PHP) ./tests/integration.sh
.PHONY: test-alpine
test-alpine: build-$(LATEST_PHP)-alpine
IMAGE=${IMAGE_NAME}:$(LATEST_PHP)-alpine ./tests/integration.sh
+120 -26
View File
@@ -20,8 +20,10 @@ This Docker image comes with **PHP-FPM**, offering a robust foundation for your
- **Database**: MySQL and PostgreSQL. - **Database**: MySQL and PostgreSQL.
- **Caching**: Redis and Memcached. - **Caching**: Redis and Memcached.
- **Messaging**: Kafka for event-driven architecture. - **Messaging**: Kafka for event-driven architecture.
- **Task Scheduling**: Laravel Scheduler and Cron jobs support. - **Task Scheduling**: Laravel Scheduler and Queue Worker started automatically (Supervisord).
- **Custom Configuration**: Pre-configured with sensible defaults, allowing seamless customization. - **Custom Configuration**: Pre-configured with sensible defaults, tunable through environment variables.
- **Debian and Alpine variants**, multi-arch (`linux/amd64`, `linux/arm64`).
- **Production-ready**: healthcheck, graceful shutdown, OPcache, `supervisorctl` support.
- **Event Handling**: Support for advanced event-driven processes. - **Event Handling**: Support for advanced event-driven processes.
- **Optimized for Microservices**: Built with modern PHP microservices in mind. - **Optimized for Microservices**: Built with modern PHP microservices in mind.
@@ -33,39 +35,44 @@ This image is ideal for developers looking for a streamlined, high-performance s
- [Github](https://github.com/jkaninda/laravel-php-fpm) - [Github](https://github.com/jkaninda/laravel-php-fpm)
--- ---
## **Supported PHP Versions** ## **Supported PHP Versions & Tags**
- 8.4
- 8.3 | PHP | Debian tag | Alpine tag |
- 8.2 |-----|------------|------------|
- 8.1 | 8.5 | `8.5`, `latest` | `8.5-alpine`, `alpine` |
- 8.0 | 8.4 | `8.4` | `8.4-alpine` |
- 7.4 | 8.3 | `8.3` | `8.3-alpine` |
- 7.2 | 8.2 | `8.2` | `8.2-alpine` |
Legacy images (PHP is end-of-life, no longer rebuilt automatically or tested): `8.1`, `8.1-alpine`, `8.0`, `7.4`, `7.3`, `7.2`.
--- ---
## **Specifications** ## **Specifications**
### **PHP Extensions** ### **PHP Extensions**
- Composer - Composer 2
- OpenSSL - OpenSSL
- XML - XML
- PDO (MySQL and PostgreSQL) - PDO (MySQL, PostgreSQL and SQLite)
- Rdkafka - Rdkafka
- Redis - Redis
- Mbstring - Mbstring
- Intl
- Exif
- PCNTL - PCNTL
- ZIP - ZIP
- GD - GD (FreeType, JPEG, PNG, WebP)
- BCMath - BCMath
- Memcached - Memcached
- Opcache - Opcache
### **Additional Features** ### **Additional Features**
- Laravel Cron Jobs
- Laravel Scheduler - Laravel Scheduler
- Laravel Queue Worker
- Supervisord - Supervisord
- Node.js and NPM - Node.js 24 LTS and NPM
- Git, Zip/Unzip, SQLite CLI
--- ---
@@ -122,7 +129,7 @@ services:
- **Fix Permissions** - **Fix Permissions**
```sh ```sh
docker compose exec php-fpm chmod -R 777 storage bootstrap/cache docker compose exec -u root php-fpm chown -R www-data:www-data storage bootstrap/cache
``` ```
- **Run Laravel Migrations** - **Run Laravel Migrations**
@@ -135,6 +142,82 @@ services:
docker exec -it php-fpm bash docker exec -it php-fpm bash
``` ```
- **Run a one-off command** (the default supervisor stack is not started)
```sh
docker run --rm -v "$PWD:/var/www/html" jkaninda/laravel-php-fpm composer install
```
- **Restart the queue workers after a deployment**
```sh
docker compose exec php-fpm supervisorctl restart all
```
---
## **Environment Variables**
### Laravel
| Variable | Default | Description |
|----------|---------|-------------|
| `LARAVEL_SCHEDULER_ENABLED` | `true` | Run `php artisan schedule:run` every minute |
| `LARAVEL_QUEUE_WORKER_ENABLED` | `true` | Run `php artisan queue:work` |
| `LARAVEL_QUEUE_OPTIONS` | `--sleep=3 --tries=3` | Options passed to `queue:work` (e.g. `redis --queue=high,default`) |
| `LARAVEL_PROCS_NUMBER` | `1` | Number of queue worker processes |
| `APP_DIR` | `/var/www/html` | Application directory (where `artisan` is looked up) |
The scheduler and queue worker are only started when an `artisan` file is found in `APP_DIR`.
### PHP
| Variable | Default |
|----------|---------|
| `PHP_MEMORY_LIMIT` | `256M` |
| `PHP_UPLOAD_MAX_FILESIZE` | `30M` |
| `PHP_POST_MAX_SIZE` | `30M` |
| `PHP_MAX_EXECUTION_TIME` | `30` |
| `PHP_DATE_TIMEZONE` | `UTC` |
| `PHP_DISPLAY_ERRORS` | `Off` |
### OPcache
| Variable | Default | Description |
|----------|---------|-------------|
| `PHP_OPCACHE_ENABLE` | `1` | |
| `PHP_OPCACHE_ENABLE_CLI` | `0` | |
| `PHP_OPCACHE_MEMORY_CONSUMPTION` | `512` | MB |
| `PHP_OPCACHE_MAX_ACCELERATED_FILES` | `50000` | |
| `PHP_OPCACHE_VALIDATE_TIMESTAMPS` | `0` | Set to `1` in development so code changes are picked up |
| `PHP_OPCACHE_REVALIDATE_FREQ` | `0` | |
### PHP-FPM
| Variable | Default |
|----------|---------|
| `PHP_FPM_PM` | `dynamic` |
| `PHP_FPM_PM_MAX_CHILDREN` | `20` |
| `PHP_FPM_PM_START_SERVERS` | `2` |
| `PHP_FPM_PM_MIN_SPARE_SERVERS` | `1` |
| `PHP_FPM_PM_MAX_SPARE_SERVERS` | `3` |
| `PHP_FPM_PM_MAX_REQUESTS` | `500` |
Container environment variables (e.g. `DB_HOST`, `APP_KEY`) are passed to PHP-FPM workers (`clear_env = no`).
### Development example
```yaml
services:
php-fpm:
image: jkaninda/laravel-php-fpm:8.5
environment:
PHP_OPCACHE_VALIDATE_TIMESTAMPS: 1
PHP_DISPLAY_ERRORS: "On"
LARAVEL_QUEUE_OPTIONS: "redis --sleep=3 --tries=3"
LARAVEL_PROCS_NUMBER: 2
volumes:
- ./:/var/www/html
```
--- ---
## **Advanced Usage with Nginx** ## **Advanced Usage with Nginx**
@@ -143,7 +226,6 @@ services:
Example of using a custom nginx config: Example of using a custom nginx config:
```yaml ```yaml
version: '3'
services: services:
php-fpm: php-fpm:
image: jkaninda/laravel-php-fpm image: jkaninda/laravel-php-fpm
@@ -206,7 +288,7 @@ server {
### **Dockerfile Example** ### **Dockerfile Example**
```Dockerfile ```Dockerfile
FROM jkaninda/laravel-php-fpm:8.3 FROM jkaninda/laravel-php-fpm:8.5
# Copy Laravel project files # Copy Laravel project files
COPY . /var/www/html COPY . /var/www/html
VOLUME /var/www/html/storage VOLUME /var/www/html/storage
@@ -240,20 +322,32 @@ stdout_logfile=/var/www/html/storage/logs/kafka.log
--- ---
## **Custom PHP Configurations** ## **Custom PHP Configurations**
Place your custom `php.ini` file at: Most common settings can be changed with [environment variables](#environment-variables).
``` For anything else, either:
/usr/local/etc/php/conf.d/
``` - mount or copy your own `.ini` file into `/usr/local/etc/php/conf.d/`, or
- place a `php.ini` file at `conf/php/php.ini` in your project; it is copied into `conf.d` at startup.
--- ---
## **Storage Permissions Fix** ## **Storage Permissions Fix**
If you encounter permission issues, run: `www-data` has UID/GID `1000` in both Debian and Alpine variants. If you encounter permission issues, run:
```sh ```sh
docker compose exec php-fpm /bin/bash docker compose exec -u root php-fpm chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
chown -R www-data:www-data /var/www/html docker compose exec -u root php-fpm chmod -R 775 /var/www/html/storage
chmod -R 775 /var/www/html/storage ```
To match your host user, rebuild with `--build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)`.
---
## **Building & Testing Locally**
```sh
make build-8.5 # Debian image
make build-8.5-alpine # Alpine image
make test # Integration test (Laravel + MySQL + Nginx)
``` ```
--- ---
+15 -15
View File
@@ -1,17 +1,17 @@
#!/bin/bash #!/bin/bash
if [ $# -eq 0 ] # Usage: ./build.sh [php-version] (default: 8.5)
then # ./build.sh 8.4-alpine
tag='latest' set -e
else tag=${1:-8.5}
tag=$1 version=${tag%-alpine}
fi
if [ $tag != 'latest' ]
then
echo 'Build from from tag'
docker build -f src/docker/${tag}/Dockerfile -t jkaninda/laravel-php-fpm:$tag .
else
echo 'Build latest'
docker build -f src/docker/8.3/Dockerfile -t jkaninda/laravel-php-fpm:$tag .
fi
if [ -f "src/docker/${version}/Dockerfile" ]; then
echo "Build legacy image ${tag}"
docker build -f "src/docker/${version}/Dockerfile" -t "jkaninda/laravel-php-fpm:${tag}" .
elif [ "${tag}" != "${version}" ]; then
echo "Build ${tag}"
docker build --build-arg phpVersion="${version}" -f src/docker/Dockerfile.alpine -t "jkaninda/laravel-php-fpm:${tag}" .
else
echo "Build ${tag}"
docker build --build-arg phpVersion="${version}" -f src/docker/Dockerfile -t "jkaninda/laravel-php-fpm:${tag}" .
fi
-1
View File
@@ -1,4 +1,3 @@
version: '3'
services: services:
php-fpm: php-fpm:
image: jkaninda/laravel-php-fpm image: jkaninda/laravel-php-fpm
+14 -1
View File
@@ -2,6 +2,19 @@ FROM php:7.2-fpm
ARG WORKDIR=/var/www/html ARG WORKDIR=/var/www/html
ENV DOCUMENT_ROOT=${WORKDIR} ENV DOCUMENT_ROOT=${WORKDIR}
ENV LARAVEL_PROCS_NUMBER=1 ENV LARAVEL_PROCS_NUMBER=1
ENV APP_DIR=/var/www/html \
PHP_DATE_TIMEZONE=UTC \
PHP_DISPLAY_ERRORS=Off \
PHP_MEMORY_LIMIT=256M \
PHP_UPLOAD_MAX_FILESIZE=30M \
PHP_POST_MAX_SIZE=30M \
PHP_MAX_EXECUTION_TIME=30 \
PHP_OPCACHE_ENABLE=1 \
PHP_OPCACHE_ENABLE_CLI=0 \
PHP_OPCACHE_MEMORY_CONSUMPTION=512 \
PHP_OPCACHE_MAX_ACCELERATED_FILES=50000 \
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
PHP_OPCACHE_REVALIDATE_FREQ=0
ENV NODE_VERSION=16.x ENV NODE_VERSION=16.x
ARG GROUP_ID=1000 ARG GROUP_ID=1000
ARG USER_ID=1000 ARG USER_ID=1000
@@ -88,7 +101,7 @@ RUN ln -s /usr/local/bin/entrypoint.sh /
ENTRYPOINT ["entrypoint.sh"] ENTRYPOINT ["entrypoint.sh"]
RUN usermod -u ${USER_ID} ${USER_NAME} RUN usermod -u ${USER_ID} ${USER_NAME}
RUN groupmod -g ${USER_ID} ${GROUP_NAME} RUN groupmod -g ${GROUP_ID} ${GROUP_NAME}
RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \ RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \
chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \
chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \
+14 -1
View File
@@ -2,6 +2,19 @@ FROM php:7.3-fpm
ARG WORKDIR=/var/www/html ARG WORKDIR=/var/www/html
ENV DOCUMENT_ROOT=${WORKDIR} ENV DOCUMENT_ROOT=${WORKDIR}
ENV LARAVEL_PROCS_NUMBER=1 ENV LARAVEL_PROCS_NUMBER=1
ENV APP_DIR=/var/www/html \
PHP_DATE_TIMEZONE=UTC \
PHP_DISPLAY_ERRORS=Off \
PHP_MEMORY_LIMIT=256M \
PHP_UPLOAD_MAX_FILESIZE=30M \
PHP_POST_MAX_SIZE=30M \
PHP_MAX_EXECUTION_TIME=30 \
PHP_OPCACHE_ENABLE=1 \
PHP_OPCACHE_ENABLE_CLI=0 \
PHP_OPCACHE_MEMORY_CONSUMPTION=512 \
PHP_OPCACHE_MAX_ACCELERATED_FILES=50000 \
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
PHP_OPCACHE_REVALIDATE_FREQ=0
ENV NODE_VERSION=16.x ENV NODE_VERSION=16.x
ARG GROUP_ID=1000 ARG GROUP_ID=1000
ARG USER_ID=1000 ARG USER_ID=1000
@@ -88,7 +101,7 @@ RUN ln -s /usr/local/bin/entrypoint.sh /
ENTRYPOINT ["entrypoint.sh"] ENTRYPOINT ["entrypoint.sh"]
RUN usermod -u ${USER_ID} ${USER_NAME} RUN usermod -u ${USER_ID} ${USER_NAME}
RUN groupmod -g ${USER_ID} ${GROUP_NAME} RUN groupmod -g ${GROUP_ID} ${GROUP_NAME}
RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \ RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \
chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \
chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \
+14 -1
View File
@@ -2,6 +2,19 @@ FROM php:7.4-fpm
ARG WORKDIR=/var/www/html ARG WORKDIR=/var/www/html
ENV DOCUMENT_ROOT=${WORKDIR} ENV DOCUMENT_ROOT=${WORKDIR}
ENV LARAVEL_PROCS_NUMBER=1 ENV LARAVEL_PROCS_NUMBER=1
ENV APP_DIR=/var/www/html \
PHP_DATE_TIMEZONE=UTC \
PHP_DISPLAY_ERRORS=Off \
PHP_MEMORY_LIMIT=256M \
PHP_UPLOAD_MAX_FILESIZE=30M \
PHP_POST_MAX_SIZE=30M \
PHP_MAX_EXECUTION_TIME=30 \
PHP_OPCACHE_ENABLE=1 \
PHP_OPCACHE_ENABLE_CLI=0 \
PHP_OPCACHE_MEMORY_CONSUMPTION=512 \
PHP_OPCACHE_MAX_ACCELERATED_FILES=50000 \
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
PHP_OPCACHE_REVALIDATE_FREQ=0
ENV NODE_VERSION=16.x ENV NODE_VERSION=16.x
ARG GROUP_ID=1000 ARG GROUP_ID=1000
ARG USER_ID=1000 ARG USER_ID=1000
@@ -89,7 +102,7 @@ RUN ln -s /usr/local/bin/entrypoint.sh /
ENTRYPOINT ["entrypoint.sh"] ENTRYPOINT ["entrypoint.sh"]
RUN usermod -u ${USER_ID} ${USER_NAME} RUN usermod -u ${USER_ID} ${USER_NAME}
RUN groupmod -g ${USER_ID} ${GROUP_NAME} RUN groupmod -g ${GROUP_ID} ${GROUP_NAME}
RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \ RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \
chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \
chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \
+14 -1
View File
@@ -2,6 +2,19 @@ FROM php:8.0-fpm
ARG WORKDIR=/var/www/html ARG WORKDIR=/var/www/html
ENV DOCUMENT_ROOT=${WORKDIR} ENV DOCUMENT_ROOT=${WORKDIR}
ENV LARAVEL_PROCS_NUMBER=1 ENV LARAVEL_PROCS_NUMBER=1
ENV APP_DIR=/var/www/html \
PHP_DATE_TIMEZONE=UTC \
PHP_DISPLAY_ERRORS=Off \
PHP_MEMORY_LIMIT=256M \
PHP_UPLOAD_MAX_FILESIZE=30M \
PHP_POST_MAX_SIZE=30M \
PHP_MAX_EXECUTION_TIME=30 \
PHP_OPCACHE_ENABLE=1 \
PHP_OPCACHE_ENABLE_CLI=0 \
PHP_OPCACHE_MEMORY_CONSUMPTION=512 \
PHP_OPCACHE_MAX_ACCELERATED_FILES=50000 \
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
PHP_OPCACHE_REVALIDATE_FREQ=0
ENV NODE_VERSION=16.x ENV NODE_VERSION=16.x
ARG GROUP_ID=1000 ARG GROUP_ID=1000
ARG USER_ID=1000 ARG USER_ID=1000
@@ -89,7 +102,7 @@ RUN ln -s /usr/local/bin/entrypoint.sh /
ENTRYPOINT ["entrypoint.sh"] ENTRYPOINT ["entrypoint.sh"]
RUN usermod -u ${USER_ID} ${USER_NAME} RUN usermod -u ${USER_ID} ${USER_NAME}
RUN groupmod -g ${USER_ID} ${GROUP_NAME} RUN groupmod -g ${GROUP_ID} ${GROUP_NAME}
RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \ RUN chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \
chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \
chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \ chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \
+85 -86
View File
@@ -1,104 +1,103 @@
ARG phpVersion=8.3-dev # syntax=docker/dockerfile:1
ARG phpVersion=8.5
FROM composer:2 AS composer
FROM php:${phpVersion}-fpm FROM php:${phpVersion}-fpm
ARG WORKDIR=/var/www/html ARG WORKDIR=/var/www/html
ENV DOCUMENT_ROOT=${WORKDIR}
ENV LARAVEL_PROCS_NUMBER=1
ENV NODE_MAJOR=20
ARG GROUP_ID=1000 ARG GROUP_ID=1000
ARG USER_ID=1000 ARG USER_ID=1000
ENV USER_NAME=www-data
ARG GROUP_NAME=www-data ARG GROUP_NAME=www-data
# Install system dependencies ARG NODE_MAJOR=24
RUN apt-get update && apt-get install -y \
git \
curl \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmemcached-dev \
libzip-dev \
libpng-dev \
libonig-dev \
libxml2-dev \
librdkafka-dev \
libpq-dev \
openssh-server \
zip \
unzip \
supervisor \
sqlite3 \
nano \
cron
# Install Nodejs
RUN apt-get update && apt-get install -y ca-certificates curl gnupg
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
RUN apt-get update && apt-get install nodejs -y
# Clear cache LABEL org.opencontainers.image.title="laravel-php-fpm" \
RUN apt-get clean && rm -rf /var/lib/apt/lists/* org.opencontainers.image.description="PHP-FPM image for Laravel and PHP applications" \
# Install Kafka org.opencontainers.image.source="https://github.com/jkaninda/laravel-php-fpm" \
RUN git clone https://github.com/arnaud-lb/php-rdkafka.git\ org.opencontainers.image.licenses="MIT" \
&& cd php-rdkafka \ org.opencontainers.image.authors="Jonas Kaninda"
&& phpize \
&& ./configure \
&& make all -j 5 \
&& make install
# Install Rdkafka and enable it ENV DOCUMENT_ROOT=${WORKDIR} \
RUN docker-php-ext-enable rdkafka \ APP_DIR=${WORKDIR} \
&& cd .. \ USER_NAME=www-data \
&& rm -rf /php-rdkafka NODE_MAJOR=${NODE_MAJOR} \
LARAVEL_PROCS_NUMBER=1 \
LARAVEL_QUEUE_WORKER_ENABLED=true \
LARAVEL_QUEUE_OPTIONS="--sleep=3 --tries=3" \
LARAVEL_SCHEDULER_ENABLED=true \
PHP_DATE_TIMEZONE=UTC \
PHP_DISPLAY_ERRORS=Off \
PHP_MEMORY_LIMIT=256M \
PHP_UPLOAD_MAX_FILESIZE=30M \
PHP_POST_MAX_SIZE=30M \
PHP_MAX_EXECUTION_TIME=30 \
PHP_OPCACHE_ENABLE=1 \
PHP_OPCACHE_ENABLE_CLI=0 \
PHP_OPCACHE_MEMORY_CONSUMPTION=512 \
PHP_OPCACHE_MAX_ACCELERATED_FILES=50000 \
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
PHP_OPCACHE_REVALIDATE_FREQ=0 \
PHP_FPM_PM=dynamic \
PHP_FPM_PM_MAX_CHILDREN=20 \
PHP_FPM_PM_START_SERVERS=2 \
PHP_FPM_PM_MIN_SPARE_SERVERS=1 \
PHP_FPM_PM_MAX_SPARE_SERVERS=3 \
PHP_FPM_PM_MAX_REQUESTS=500
# Install PHP extensions zip, mbstring, exif, bcmath, intl # Runtime tools and Node.js
RUN docker-php-ext-configure gd --with-freetype --with-jpeg RUN set -eux; \
RUN docker-php-ext-install zip mbstring exif pcntl bcmath -j$(nproc) gd intl apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates curl gnupg git openssh-client unzip zip \
supervisor cron sqlite3 nano; \
mkdir -p /etc/apt/keyrings; \
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" > /etc/apt/sources.list.d/nodesource.list; \
apt-get update; \
apt-get install -y --no-install-recommends nodejs; \
rm -rf /var/lib/apt/lists/*
# Install Redis and enable it # PHP extensions (build dependencies are purged, runtime libraries are kept)
RUN pecl install redis && docker-php-ext-enable redis RUN set -eux; \
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
libfreetype6-dev libjpeg62-turbo-dev libpng-dev libwebp-dev \
libicu-dev libmemcached-dev libonig-dev libpq-dev librdkafka-dev \
libxml2-dev libzip-dev zlib1g-dev; \
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp; \
docker-php-ext-install -j"$(nproc)" bcmath exif gd intl mbstring pcntl pdo_mysql pdo_pgsql zip; \
pecl install redis memcached rdkafka; \
docker-php-ext-enable redis memcached rdkafka; \
# OPcache is always compiled in since PHP 8.5
if ! php -m | grep -qi '^zend opcache$'; then docker-php-ext-install opcache; fi; \
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
find /usr/local -type f \( -executable -o -name '*.so' \) -exec ldd '{}' ';' 2>/dev/null \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); printf "*%s\n", so }' \
| sort -u | xargs -r dpkg-query --search | awk -F: '!/^diversion/ { print $1 }' | sort -u | xargs -r apt-mark manual; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/* /tmp/pear ~/.pearrc; \
! php -m 2>&1 | grep -iE 'warning|unable to load'
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
# Install the php memcached extension
RUN pecl install memcached && docker-php-ext-enable memcached
# Install the PHP pdo_mysql extention
RUN docker-php-ext-install pdo_mysql
# Install the PHP pdo_pgsql extention
RUN docker-php-ext-install pdo_pgsql
# Install PHP Opcache extention
RUN docker-php-ext-install opcache
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Set working directory
WORKDIR $WORKDIR WORKDIR $WORKDIR
RUN rm -Rf /var/www/* && \ RUN rm -Rf /var/www/* && mkdir -p ${WORKDIR} /etc/supervisor/conf.d /var/log/supervisor
mkdir -p /var/www/html
ADD src/index.php $WORKDIR/index.php COPY src/index.php $WORKDIR/index.php
ADD src/php.ini $PHP_INI_DIR/conf.d/ COPY src/php.ini src/opcache.ini $PHP_INI_DIR/conf.d/
ADD src/opcache.ini $PHP_INI_DIR/conf.d/ COPY src/php-fpm.d/zz-laravel.conf /usr/local/etc/php-fpm.d/zz-laravel.conf
ADD src/supervisor/supervisord.conf /etc/supervisor/supervisord.conf COPY src/supervisor/supervisord.conf /etc/supervisor/supervisord.conf
COPY --chmod=755 src/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY src/entrypoint.sh /usr/local/bin/ RUN ln -s /usr/local/bin/entrypoint.sh /entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
RUN ln -s /usr/local/bin/entrypoint.sh /
ENTRYPOINT ["entrypoint.sh"]
RUN usermod -u ${USER_ID} ${USER_NAME} && \ RUN usermod -u ${USER_ID} ${USER_NAME} && \
groupmod -g ${USER_ID} ${GROUP_NAME} && \ groupmod -g ${GROUP_ID} ${GROUP_NAME} && \
chown -R ${USER_NAME}:${GROUP_NAME} /var/www && \ chown -R ${USER_NAME}:${GROUP_NAME} /var/www /var/log /etc/supervisor/conf.d $PHP_INI_DIR/conf.d /tmp
chown -R ${USER_NAME}:${GROUP_NAME} /var/log/ && \
chown -R ${USER_NAME}:${GROUP_NAME} /etc/supervisor/conf.d/ && \ HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --start-interval=2s --retries=3 \
chown -R ${USER_NAME}:${GROUP_NAME} $PHP_INI_DIR/conf.d/ && \ CMD php -r 'exit(@fsockopen("127.0.0.1", 9000) ? 0 : 1);'
chown -R ${USER_NAME}:${GROUP_NAME} /tmp
EXPOSE 9000 EXPOSE 9000
CMD [ "entrypoint" ] ENTRYPOINT ["entrypoint.sh"]
CMD ["entrypoint"]
+82 -13
View File
@@ -1,24 +1,93 @@
ARG phpVersion=8.3-dev # syntax=docker/dockerfile:1
ARG phpVersion=8.5
FROM composer:2 AS composer
FROM php:${phpVersion}-fpm-alpine FROM php:${phpVersion}-fpm-alpine
ARG WORKDIR=/var/www/html ARG WORKDIR=/var/www/html
ENV DOCUMENT_ROOT=${WORKDIR}
ENV LARAVEL_PROCS_NUMBER=1
ARG GROUP_ID=1000 ARG GROUP_ID=1000
ARG USER_ID=1000 ARG USER_ID=1000
ENV USER_NAME=www-data
ARG GROUP_NAME=www-data ARG GROUP_NAME=www-data
# Install the PHP pdo_mysql extention LABEL org.opencontainers.image.title="laravel-php-fpm" \
RUN docker-php-ext-install pdo_mysql org.opencontainers.image.description="PHP-FPM image for Laravel and PHP applications (Alpine)" \
org.opencontainers.image.source="https://github.com/jkaninda/laravel-php-fpm" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.authors="Jonas Kaninda"
# Install Composer ENV DOCUMENT_ROOT=${WORKDIR} \
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer APP_DIR=${WORKDIR} \
USER_NAME=www-data \
LARAVEL_PROCS_NUMBER=1 \
LARAVEL_QUEUE_WORKER_ENABLED=true \
LARAVEL_QUEUE_OPTIONS="--sleep=3 --tries=3" \
LARAVEL_SCHEDULER_ENABLED=true \
PHP_DATE_TIMEZONE=UTC \
PHP_DISPLAY_ERRORS=Off \
PHP_MEMORY_LIMIT=256M \
PHP_UPLOAD_MAX_FILESIZE=30M \
PHP_POST_MAX_SIZE=30M \
PHP_MAX_EXECUTION_TIME=30 \
PHP_OPCACHE_ENABLE=1 \
PHP_OPCACHE_ENABLE_CLI=0 \
PHP_OPCACHE_MEMORY_CONSUMPTION=512 \
PHP_OPCACHE_MAX_ACCELERATED_FILES=50000 \
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
PHP_OPCACHE_REVALIDATE_FREQ=0 \
PHP_FPM_PM=dynamic \
PHP_FPM_PM_MAX_CHILDREN=20 \
PHP_FPM_PM_START_SERVERS=2 \
PHP_FPM_PM_MIN_SPARE_SERVERS=1 \
PHP_FPM_PM_MAX_SPARE_SERVERS=3 \
PHP_FPM_PM_MAX_REQUESTS=500
# Runtime tools and Node.js
RUN apk add --no-cache bash curl git openssh-client unzip zip supervisor sqlite nano nodejs npm
# PHP extensions (build dependencies are removed, runtime libraries are kept)
RUN set -eux; \
apk add --no-cache --virtual .build-deps $PHPIZE_DEPS \
freetype-dev libjpeg-turbo-dev libpng-dev libwebp-dev \
icu-dev libmemcached-dev oniguruma-dev libpq-dev librdkafka-dev \
libxml2-dev libzip-dev zlib-dev cyrus-sasl-dev linux-headers; \
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp; \
docker-php-ext-install -j"$(nproc)" bcmath exif gd intl mbstring pcntl pdo_mysql pdo_pgsql zip; \
pecl install redis memcached rdkafka; \
docker-php-ext-enable redis memcached rdkafka; \
# OPcache is always compiled in since PHP 8.5
if ! php -m | grep -qi '^zend opcache$'; then docker-php-ext-install opcache; fi; \
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
| tr ',' '\n' | sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache --virtual .php-ext-rundeps $runDeps; \
apk del --no-network .build-deps; \
rm -rf /tmp/pear ~/.pearrc; \
! php -m 2>&1 | grep -iE 'warning|unable to load'
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
# Set working directory
WORKDIR $WORKDIR WORKDIR $WORKDIR
RUN rm -Rf /var/www/* && \ RUN rm -Rf /var/www/* && mkdir -p ${WORKDIR} /etc/supervisor/conf.d /var/log/supervisor
mkdir -p /var/www/html
ADD src/index.php $WORKDIR/index.php COPY src/index.php $WORKDIR/index.php
ADD src/php.ini $PHP_INI_DIR/conf.d/ COPY src/php.ini src/opcache.ini $PHP_INI_DIR/conf.d/
COPY src/php-fpm.d/zz-laravel.conf /usr/local/etc/php-fpm.d/zz-laravel.conf
COPY src/supervisor/supervisord.conf /etc/supervisor/supervisord.conf
COPY --chmod=755 src/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN ln -s /usr/local/bin/entrypoint.sh /entrypoint.sh && \
ln -sf /etc/supervisor/supervisord.conf /etc/supervisord.conf
RUN apk add --no-cache --virtual .user-deps shadow && \
usermod -u ${USER_ID} ${USER_NAME} && \
groupmod -g ${GROUP_ID} ${GROUP_NAME} && \
apk del --no-network .user-deps && \
chown -R ${USER_NAME}:${GROUP_NAME} /var/www /var/log /etc/supervisor/conf.d $PHP_INI_DIR/conf.d /tmp
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --start-interval=2s --retries=3 \
CMD php -r 'exit(@fsockopen("127.0.0.1", 9000) ? 0 : 1);'
EXPOSE 9000
ENTRYPOINT ["entrypoint.sh"]
CMD ["entrypoint"]
+52 -23
View File
@@ -1,13 +1,12 @@
#!/bin/bash #!/bin/sh
set -e set -e
# Logging functions # Logging functions
log() { log() {
local level=$1 level=$1
shift shift
{ set +x; } 2> /dev/null echo "[$level] $*"
echo "[$level] $@"
} }
info() { info() {
@@ -23,6 +22,32 @@ fatal() {
exit 1 exit 1
} }
is_true() {
case "$1" in
1|true|TRUE|True|yes|YES|on|ON) return 0 ;;
*) return 1 ;;
esac
}
APP_DIR="${APP_DIR:-/var/www/html}"
USER_NAME="${USER_NAME:-www-data}"
LARAVEL_PROCS_NUMBER="${LARAVEL_PROCS_NUMBER:-1}"
LARAVEL_QUEUE_OPTIONS="${LARAVEL_QUEUE_OPTIONS:---sleep=3 --tries=3}"
# Check if custom php.ini file exists
PHP_INI_SOURCE="$APP_DIR/conf/php/php.ini"
PHP_INI_TARGET="$PHP_INI_DIR/conf.d/php.ini"
if [ -f "$PHP_INI_SOURCE" ]; then
cp "$PHP_INI_SOURCE" "$PHP_INI_TARGET"
info "Custom php.ini file found and copied to $PHP_INI_TARGET"
fi
# Run any other command (e.g. "php artisan migrate", "composer install", "bash")
if [ $# -gt 0 ] && [ "$1" != "entrypoint" ] && [ "$1" != "supervisord" ]; then
exec "$@"
fi
# Banner # Banner
echo "" echo ""
echo "***********************************************************" echo "***********************************************************"
@@ -30,13 +55,14 @@ echo " Starting LARAVEL PHP-FPM Container "
echo "***********************************************************" echo "***********************************************************"
# Check if the artisan file exists # Check if the artisan file exists
ARTISAN_PATH="/var/www/html/artisan" ARTISAN_PATH="$APP_DIR/artisan"
if [[ -f "$ARTISAN_PATH" ]]; then SUPERVISOR_TASK="/etc/supervisor/conf.d/laravel-worker.conf"
if [ -f "$ARTISAN_PATH" ]; then
info "Artisan file found, creating Laravel supervisor config..." info "Artisan file found, creating Laravel supervisor config..."
: > "$SUPERVISOR_TASK"
# Create Laravel Supervisor config if is_true "${LARAVEL_SCHEDULER_ENABLED:-true}"; then
SUPERVISOR_TASK="/etc/supervisor/conf.d/laravel-worker.conf" cat >> "$SUPERVISOR_TASK" <<EOF
cat > "$SUPERVISOR_TASK" <<EOF
[program:Laravel-scheduler] [program:Laravel-scheduler]
process_name=%(program_name)s_%(process_num)02d process_name=%(program_name)s_%(process_num)02d
command=/bin/sh -c "while true; do php $ARTISAN_PATH schedule:run --verbose --no-interaction & sleep 60; done" command=/bin/sh -c "while true; do php $ARTISAN_PATH schedule:run --verbose --no-interaction & sleep 60; done"
@@ -47,33 +73,36 @@ user=$USER_NAME
stdout_logfile=/var/log/laravel_scheduler.out.log stdout_logfile=/var/log/laravel_scheduler.out.log
redirect_stderr=true redirect_stderr=true
EOF
info "Laravel scheduler enabled"
fi
if is_true "${LARAVEL_QUEUE_WORKER_ENABLED:-true}"; then
cat >> "$SUPERVISOR_TASK" <<EOF
[program:Laravel-worker] [program:Laravel-worker]
process_name=%(program_name)s_%(process_num)02d process_name=%(program_name)s_%(process_num)02d
command=php $ARTISAN_PATH queue:work --sleep=3 --tries=3 command=php $ARTISAN_PATH queue:work $LARAVEL_QUEUE_OPTIONS
autostart=true autostart=true
autorestart=true autorestart=true
; Keep retrying while the database/queue backend is not ready yet
startretries=20
stopwaitsecs=3600
numprocs=$LARAVEL_PROCS_NUMBER numprocs=$LARAVEL_PROCS_NUMBER
user=$USER_NAME user=$USER_NAME
redirect_stderr=true redirect_stderr=true
stdout_logfile=/var/log/laravel_worker.log stdout_logfile=/var/log/laravel_worker.log
EOF EOF
info "Laravel queue worker enabled ($LARAVEL_PROCS_NUMBER process(es))"
fi
info "Laravel supervisor config created at $SUPERVISOR_TASK" info "Laravel supervisor config created at $SUPERVISOR_TASK"
else else
rm -f "$SUPERVISOR_TASK" 2>/dev/null || true
info "Artisan file not found at $ARTISAN_PATH" info "Artisan file not found at $ARTISAN_PATH"
fi fi
# Check if custom php.ini file exists # Start Supervisor (programs drop privileges to $USER_NAME themselves)
PHP_INI_SOURCE="/var/www/html/conf/php/php.ini" if [ "$(id -u)" = "0" ]; then
PHP_INI_TARGET="$PHP_INI_DIR/conf.d/php.ini" exec supervisord -c /etc/supervisor/supervisord.conf -u root
if [[ -f "$PHP_INI_SOURCE" ]]; then
cp "$PHP_INI_SOURCE" "$PHP_INI_TARGET"
info "Custom php.ini file found and copied to $PHP_INI_TARGET"
else
info "Custom php.ini file not found at $PHP_INI_SOURCE"
info "To use a custom php.ini file, place it at $PHP_INI_SOURCE"
fi fi
exec supervisord -c /etc/supervisor/supervisord.conf
# Start Supervisor
supervisord -c /etc/supervisor/supervisord.conf
+8 -12
View File
@@ -1,12 +1,12 @@
[opcache] [opcache]
; Determines if Zend OPCache is enabled ; Determines if Zend OPCache is enabled
opcache.enable=1 opcache.enable=${PHP_OPCACHE_ENABLE}
; Determines if Zend OPCache is enabled for the CLI version of PHP ; Determines if Zend OPCache is enabled for the CLI version of PHP
;opcache.enable_cli=1 opcache.enable_cli=${PHP_OPCACHE_ENABLE_CLI}
; The OPcache shared memory storage size. ; The OPcache shared memory storage size.
opcache.memory_consumption=512 opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION}
; The amount of memory for interned strings in Mbytes. ; The amount of memory for interned strings in Mbytes.
opcache.interned_strings_buffer=64 opcache.interned_strings_buffer=64
@@ -15,7 +15,7 @@ opcache.interned_strings_buffer=64
; Only numbers between 200 and 1000000 are allowed. ; Only numbers between 200 and 1000000 are allowed.
;If you have multiple PHP sites on the server then consider the value 130986 ;If you have multiple PHP sites on the server then consider the value 130986
; for magento 2, keep 65406 ; for magento 2, keep 65406
opcache.max_accelerated_files=50000 opcache.max_accelerated_files=${PHP_OPCACHE_MAX_ACCELERATED_FILES}
; The maximum percentage of "wasted" memory until a restart is scheduled. ; The maximum percentage of "wasted" memory until a restart is scheduled.
opcache.max_wasted_percentage=15 opcache.max_wasted_percentage=15
@@ -30,7 +30,7 @@ opcache.max_wasted_percentage=15
; webserver for changes to the filesystem to take effect. ; webserver for changes to the filesystem to take effect.
; For Development / testing, keep 1 ; For Development / testing, keep 1
; For performance / production, keep 0 ; For performance / production, keep 0
opcache.validate_timestamps=0 opcache.validate_timestamps=${PHP_OPCACHE_VALIDATE_TIMESTAMPS}
;opcache.revalidate_freq How often in seconds should the code ;opcache.revalidate_freq How often in seconds should the code
;cache expire and check if your code has changed. 0 means it ;cache expire and check if your code has changed. 0 means it
@@ -39,7 +39,7 @@ opcache.validate_timestamps=0
;should not be enabled by default, as long as it's disabled then any value for opcache. ;should not be enabled by default, as long as it's disabled then any value for opcache.
;revalidate_freq will basically be ignored. You should really only ever enable ;revalidate_freq will basically be ignored. You should really only ever enable
;this during development, you don't really want to enable this setting for a production application. ;this during development, you don't really want to enable this setting for a production application.
opcache.revalidate_freq=0 opcache.revalidate_freq=${PHP_OPCACHE_REVALIDATE_FREQ}
; Enables or disables file search in include_path optimization ; Enables or disables file search in include_path optimization
;opcache.revalidate_path=0 ;opcache.revalidate_path=0
@@ -48,10 +48,6 @@ opcache.revalidate_freq=0
; size of the optimized code. ; size of the optimized code.
opcache.save_comments=1 opcache.save_comments=1
; If enabled, a fast shutdown sequence is used for the accelerated code
; Depending on the used Memory Manager this may cause some incompatibilities.
opcache.fast_shutdown=1
; Allow file existence override (file_exists, etc.) performance feature. ; Allow file existence override (file_exists, etc.) performance feature.
;opcache.enable_file_override=0 ;opcache.enable_file_override=0
@@ -106,7 +102,7 @@ opcache.fast_shutdown=1
; processes have to map shared memory into the same address space. This ; processes have to map shared memory into the same address space. This
; directive allows to manually fix the "Unable to reattach to base address" ; directive allows to manually fix the "Unable to reattach to base address"
; errors. ; errors.
opcache.mmap_base=0x20000000 ;opcache.mmap_base=
; Enables and sets the second level cache directory. ; Enables and sets the second level cache directory.
; It should improve performance when SHM memory is full, at server restart or ; It should improve performance when SHM memory is full, at server restart or
@@ -122,7 +118,7 @@ opcache.mmap_base=0x20000000
; Implies opcache.file_cache_only=1 for a certain process that failed to ; Implies opcache.file_cache_only=1 for a certain process that failed to
; reattach to the shared memory (for Windows only). Explicitly enabled file ; reattach to the shared memory (for Windows only). Explicitly enabled file
; cache is required. ; cache is required.
opcache.file_cache_fallback=1 ;opcache.file_cache_fallback=1
; Enables or disables copying of PHP code (text segment) into HUGE PAGES. ; Enables or disables copying of PHP code (text segment) into HUGE PAGES.
; This should improve performance, but requires appropriate OS configuration. ; This should improve performance, but requires appropriate OS configuration.
+15
View File
@@ -0,0 +1,15 @@
[www]
; Expose container environment variables (DB_HOST, APP_KEY, ...) to PHP workers
clear_env = no
; Process manager, tunable through PHP_FPM_* environment variables
pm = ${PHP_FPM_PM}
pm.max_children = ${PHP_FPM_PM_MAX_CHILDREN}
pm.start_servers = ${PHP_FPM_PM_START_SERVERS}
pm.min_spare_servers = ${PHP_FPM_PM_MIN_SPARE_SERVERS}
pm.max_spare_servers = ${PHP_FPM_PM_MAX_SPARE_SERVERS}
pm.max_requests = ${PHP_FPM_PM_MAX_REQUESTS}
; Health endpoint for FastCGI probes
ping.path = /ping
ping.response = pong
+8 -5
View File
@@ -1,6 +1,9 @@
date.timezone=UTC ; Values can be overridden with environment variables (see README)
display_errors=Off date.timezone=${PHP_DATE_TIMEZONE}
display_errors=${PHP_DISPLAY_ERRORS}
log_errors=On log_errors=On
upload_max_filesize= 30M expose_php=Off
post_max_size= 30M upload_max_filesize=${PHP_UPLOAD_MAX_FILESIZE}
memory_limit = 256M post_max_size=${PHP_POST_MAX_SIZE}
memory_limit=${PHP_MEMORY_LIMIT}
max_execution_time=${PHP_MAX_EXECUTION_TIME}
+13 -5
View File
@@ -1,23 +1,31 @@
[supervisord] [supervisord]
nodaemon=true nodaemon=true
user=%(ENV_USER_NAME)s
logfile=/var/log/supervisor/supervisord.log logfile=/var/log/supervisor/supervisord.log
logfile_maxbytes = 50MB logfile_maxbytes = 50MB
pidfile=/tmp/supervisord.pid pidfile=/tmp/supervisord.pid
directory = /tmp directory = /tmp
[unix_http_server]
file=/tmp/supervisor.sock
chmod=0700
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock
[program:php-fpm] [program:php-fpm]
command=/usr/local/sbin/php-fpm command=/usr/local/sbin/php-fpm --nodaemonize
numprocs=1 numprocs=1
autostart=true autostart=true
autorestart=true autorestart=true
redirect_stderr=true redirect_stderr=true
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout
stderr_logfile=/dev/stdout
stdout_logfile_maxbytes=0 stdout_logfile_maxbytes=0
user=www-data
priority=1 priority=1
stopsignal=QUIT
[include] [include]
files = /etc/supervisor/conf.d/*.conf files = /etc/supervisor/conf.d/*.conf
+43 -39
View File
@@ -1,41 +1,45 @@
version: '3'
services: services:
mysql: mysql:
image: mysql:8.0 image: mysql:8.4
container_name: mysql container_name: mysql
restart: unless-stopped restart: unless-stopped
environment: environment:
MYSQL_DATABASE: php MYSQL_DATABASE: php
MYSQL_ROOT_PASSWORD: password MYSQL_ROOT_PASSWORD: password
MYSQL_PASSWORD: password MYSQL_PASSWORD: password
MYSQL_USER: php MYSQL_USER: php
ports: healthcheck:
- 3306:3306 test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-ppassword"]
php-fpm: interval: 5s
image: jkaninda/laravel-php-fpm:latest timeout: 5s
container_name: php-fpm retries: 30
restart: unless-stopped php-fpm:
#user: www-data #Use www-data user production usage image: ${IMAGE:-jkaninda/laravel-php-fpm:latest}
depends_on: container_name: php-fpm
- mysql restart: unless-stopped
environment: depends_on:
DB_HOST: mysql mysql:
DB_PORT: 3306 condition: service_healthy
DB_DATABASE: php environment:
DB_USERNAME: php DB_CONNECTION: mysql
DB_PASSWORD: password DB_HOST: mysql
volumes: DB_PORT: 3306
- ./laravel:/var/www/html DB_DATABASE: php
#Nginx server DB_USERNAME: php
nginx-server: DB_PASSWORD: password
image: jkaninda/nginx-fpm:stable volumes:
container_name: nginx-server
restart: unless-stopped
ports:
- 80:80
volumes:
- ./laravel:/var/www/html - ./laravel:/var/www/html
environment: nginx-server:
- DOCUMENT_ROOT=/var/www/html/public image: jkaninda/nginx-fpm:stable
- CLIENT_MAX_BODY_SIZE=20M container_name: nginx-server
- PHP_FPM_HOST=php-fpm:9000 restart: unless-stopped
depends_on:
- php-fpm
ports:
- "${HTTP_PORT:-80}:80"
volumes:
- ./laravel:/var/www/html
environment:
- DOCUMENT_ROOT=/var/www/html/public
- CLIENT_MAX_BODY_SIZE=20M
- PHP_FPM_HOST=php-fpm:9000
+65
View File
@@ -0,0 +1,65 @@
#!/bin/sh
# Integration test: create a Laravel project with the image, serve it through
# Nginx, run migrations and check that PHP-FPM, the queue worker and the
# scheduler are running.
# Usage: IMAGE=jkaninda/laravel-php-fpm:8.5 [HTTP_PORT=8080] ./tests/integration.sh
set -eu
IMAGE="${IMAGE:-jkaninda/laravel-php-fpm:latest}"
HTTP_PORT="${HTTP_PORT:-80}"
export IMAGE HTTP_PORT
cd "$(dirname "$0")"
cleanup() {
docker compose logs php-fpm || true
docker compose down -v --remove-orphans || true
}
trap cleanup EXIT
echo "==> Checking PHP extensions"
docker run --rm "$IMAGE" php -m > modules.txt
for ext in bcmath exif gd intl mbstring memcached pcntl pdo_mysql pdo_pgsql rdkafka redis zip "Zend OPcache"; do
grep -qx "$ext" modules.txt || { echo "Missing extension: $ext"; exit 1; }
done
if docker run --rm "$IMAGE" php -m 2>&1 | grep -iE 'warning|unable to load'; then
echo "PHP startup warnings detected"; exit 1
fi
rm -f modules.txt
docker run --rm "$IMAGE" sh -c 'php -v && composer -V && node -v && npm -v'
echo "==> Creating Laravel project"
rm -rf laravel
docker run --rm -v "$PWD:/app" -w /app "$IMAGE" \
composer create-project --prefer-dist --no-interaction --no-progress laravel/laravel laravel
docker run --rm -v "$PWD/laravel:/var/www/html" "$IMAGE" \
chown -R www-data:www-data storage bootstrap/cache database
echo "==> Starting stack"
docker compose up -d
echo "==> Waiting for PHP-FPM to be healthy"
i=0
until [ "$(docker inspect -f '{{.State.Health.Status}}' php-fpm)" = "healthy" ]; do
i=$((i + 1)); [ "$i" -gt 60 ] && { echo "PHP-FPM not healthy"; exit 1; }
sleep 2
done
echo "==> Running migrations"
docker exec --user www-data php-fpm php artisan migrate --force
echo "==> Checking HTTP response"
code=$(curl -s -o /dev/null -w '%{http_code}' "http://localhost:$HTTP_PORT")
echo "HTTP $code"
[ "$code" = "200" ]
echo "==> Checking supervisor programs"
for program in php-fpm Laravel-worker Laravel-scheduler; do
i=0
until docker exec php-fpm supervisorctl status | grep "^$program" | grep -q RUNNING; do
i=$((i + 1)); [ "$i" -gt 30 ] && { echo "$program is not running"; docker exec php-fpm supervisorctl status; exit 1; }
sleep 2
done
done
docker exec php-fpm supervisorctl status
echo "==> All tests passed"