Repository navigation
Add optional Docker Compose deployment #184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
srdco
wants to merge
20
commits into
jjdejong:master
Choose a base branch
from
srdco:codex/docker-upstream-only
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
af4942b
Add Docker deployment to feature list
d31973b
Align MySQL timezone with application
srdco 695e960
Document App Platform key and proxy settings
srdco 97c4555
Address App Platform deployment review feedback
srdco 9444806
Address App Platform deployment review feedback
srdco 6550e56
Address App Platform deployment review feedback
srdco 48fd896
Address App Platform deployment review feedback
srdco 573ba98
Address App Platform deployment review feedback
srdco cea3f0f
Address App Platform deployment review feedback
srdco 99dcdd8
Fix Docker review follow-up findings
srdco 6249f34
Fix Docker review follow-up findings
srdco ef11a37
Fix Docker review follow-up findings
srdco 882d9ba
Fix Docker review follow-up findings
srdco 7c66dff
Fix Docker review follow-up findings
srdco 539d5e6
Fix Docker review follow-up findings
srdco 0429a6c
Clarify App Platform logging and backup paths
srdco 2d4ee1b
Complete App Platform deployment setup
srdco 1b976dc
Complete App Platform deployment setup
srdco 1df8df9
Complete App Platform deployment setup
srdco 174bc70
Document secure single-instance App Platform setup
srdco File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| .git | ||
| .env | ||
| .env.* | ||
| !.env.example | ||
| node_modules | ||
| vendor | ||
| public/build | ||
| public/hot | ||
| public/storage | ||
| bootstrap/cache/*.php | ||
| storage/** | ||
| !storage/**/.gitignore | ||
| config/renewal.php | ||
| config/renewr.php | ||
| *.log | ||
| *.sql.gz | ||
| *-backup.sql | ||
| *.tar.gz | ||
| backups |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| APP_NAME=phpIP | ||
| COMPANY_NAME="My Company" | ||
| APP_ENV=production | ||
| APP_DEBUG=false | ||
| APP_KEY= | ||
| APP_URL=http://localhost:8000 | ||
| APP_BIND_ADDRESS=127.0.0.1 | ||
| APP_PORT=8000 | ||
| APP_LOCALE=en_US | ||
| APP_TIMEZONE=America/Chicago | ||
| # Optional comma-separated IPs/CIDRs of TLS-terminating reverse proxies. | ||
| TRUSTED_PROXIES= | ||
|
|
||
| DB_DATABASE=phpip | ||
| DB_USERNAME=phpip | ||
| DB_PASSWORD= | ||
| MYSQL_ROOT_PASSWORD= | ||
|
|
||
| # Set a unique value before the first seed when APP_ENV=production. | ||
| # Non-production seeds fall back to the documented `changeme` password. | ||
| INITIAL_USER_PASSWORD= | ||
|
|
||
| # Log mail locally until SMTP and recipients are configured. | ||
| MAIL_MAILER=log | ||
| MAIL_FROM_ADDRESS=noreply@example.com | ||
| MAIL_FROM_NAME=phpIP | ||
| MAIL_TO= | ||
|
|
||
| # Configure integrations before enabling the scheduler profile. | ||
| OPS_APP_KEY= | ||
| OPS_SECRET= | ||
| RENEWR_API_URL=https://demo-api.renewr.io/api/external/patent/with-renewal-event-and-fees | ||
| RENEWR_API_KEY= | ||
| SHAREPOINT_ENABLED=false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| name: Docker | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main, master] | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| smoke: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Create isolated test configuration | ||
| run: | | ||
| python3 - <<'PY' | ||
| import base64, os, pathlib, secrets | ||
| text = pathlib.Path('.env.docker.example').read_text() | ||
| values = { | ||
| 'APP_KEY': 'base64:' + base64.b64encode(secrets.token_bytes(32)).decode(), | ||
| 'DB_PASSWORD': secrets.token_hex(24), | ||
| 'MYSQL_ROOT_PASSWORD': secrets.token_hex(24), | ||
| 'INITIAL_USER_PASSWORD': secrets.token_urlsafe(24), | ||
| } | ||
| for key, value in values.items(): | ||
| text = text.replace(key + '=\n', key + '=' + value + '\n') | ||
| pathlib.Path('.env.docker').write_text(text) | ||
| with pathlib.Path(os.environ['GITHUB_ENV']).open('a') as env_file: | ||
| env_file.write('INITIAL_USER_PASSWORD=' + values['INITIAL_USER_PASSWORD'] + '\n') | ||
| PY | ||
| - name: Build and initialize | ||
| run: | | ||
| docker compose --env-file .env.docker config --quiet | ||
| docker compose --env-file .env.docker build app | ||
| docker compose --env-file .env.docker up -d --wait db | ||
| docker compose --env-file .env.docker run --rm app php artisan migrate --force | ||
| docker compose --env-file .env.docker run --rm app php artisan db:seed --force | ||
| docker compose --env-file .env.docker up -d --wait app | ||
| docker compose --env-file .env.docker exec -T app php artisan config:show renewal.invoice.captions | ||
| docker compose --env-file .env.docker exec -T app php artisan config:show renewr.url | ||
| - name: Verify application and container replacement | ||
| run: | | ||
| docker compose --env-file .env.docker exec -T app sh -c 'test -z "$MYSQL_ROOT_PASSWORD"' | ||
| python3 tests/docker-smoke.py | ||
| docker compose --env-file .env.docker exec -T app php artisan schedule:list | ||
| docker compose --env-file .env.docker exec -T --user www-data app sh -c 'printf docker-persistence > storage/app/docker-smoke-check' | ||
| docker compose --env-file .env.docker up -d --wait --force-recreate app | ||
| docker compose --env-file .env.docker exec -T --user www-data app sh -c 'test "$(cat storage/app/docker-smoke-check)" = docker-persistence && rm storage/app/docker-smoke-check' | ||
| python3 tests/docker-smoke.py | ||
| docker compose --env-file .env.docker run --rm app php artisan migrate --force | ||
| - name: Container diagnostics | ||
| if: failure() | ||
| run: docker compose --env-file .env.docker logs --tail=100 | ||
| - name: Remove isolated test stack | ||
| if: always() | ||
| run: docker compose --env-file .env.docker --profile scheduler down -v | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # syntax=docker/dockerfile:1 | ||
| FROM node:22-bookworm-slim AS assets | ||
| WORKDIR /app | ||
| COPY package.json yarn.lock ./ | ||
| RUN --mount=type=secret,id=proxy_ca \ | ||
| if [ -f /run/secrets/proxy_ca ]; then export NODE_EXTRA_CA_CERTS=/run/secrets/proxy_ca; fi; \ | ||
| yarn install --frozen-lockfile | ||
| COPY resources ./resources | ||
| COPY vite.config.js ./ | ||
| RUN yarn build | ||
|
|
||
| FROM php:8.4-apache-bookworm AS php-base | ||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| default-mysql-client gosu libfreetype6-dev libjpeg62-turbo-dev libpng-dev \ | ||
| libicu-dev libonig-dev libxml2-dev libzip-dev unzip \ | ||
| && docker-php-ext-configure gd --with-freetype --with-jpeg \ | ||
| && docker-php-ext-install -j"$(nproc)" gd intl mbstring pdo_mysql zip opcache \ | ||
|
srdco marked this conversation as resolved.
Resolved
|
||
| && a2enmod rewrite \ | ||
| && sed -i 's/^Listen 80$/Listen 8080/' /etc/apache2/ports.conf \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
| COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer | ||
| WORKDIR /var/www/html | ||
| COPY --chmod=0644 docker/apache.conf /etc/apache2/sites-available/000-default.conf | ||
| COPY --chmod=0644 docker/php.ini /usr/local/etc/php/conf.d/phpip.ini | ||
| COPY --chmod=0755 docker/entrypoint.sh /usr/local/bin/phpip-entrypoint | ||
| ENTRYPOINT ["/bin/sh", "/usr/local/bin/phpip-entrypoint"] | ||
| CMD ["apache2-foreground"] | ||
| EXPOSE 8080 | ||
|
|
||
| FROM php-base AS dependencies | ||
| COPY composer.json composer.lock ./ | ||
| RUN --mount=type=secret,id=proxy_ca \ | ||
| if [ -f /run/secrets/proxy_ca ]; then export COMPOSER_CAFILE=/run/secrets/proxy_ca; fi; \ | ||
| composer install --no-dev --no-scripts --prefer-dist --no-interaction --no-progress | ||
|
|
||
| FROM php-base AS application | ||
| COPY . . | ||
| COPY --from=dependencies /var/www/html/vendor ./vendor | ||
| COPY --from=assets /app/public/build ./public/build | ||
| # Use the importing account as definer, rather than phpip@localhost from the dump. | ||
| RUN chmod -R u=rwX,go=rX . \ | ||
| && cp config/renewal.example.php config/renewal.php \ | ||
| && cp config/renewr.example.php config/renewr.php \ | ||
| && sed -i 's/DEFINER=`[^`]*`@`[^`]*`//g' database/schema/mysql-schema.sql \ | ||
| && mkdir -p storage/app/public storage/app/cache storage/framework/cache/data \ | ||
| storage/framework/sessions storage/framework/views storage/logs bootstrap/cache \ | ||
| && composer dump-autoload --no-dev --optimize --no-interaction \ | ||
| && ln -s /var/www/html/storage/app/public public/storage \ | ||
| && chown -R www-data:www-data storage bootstrap/cache | ||
| HEALTHCHECK --interval=30s --timeout=5s --start-period=20s \ | ||
| CMD curl --fail --silent http://127.0.0.1:8080/up || exit 1 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| name: phpip | ||
|
|
||
| x-application: &application | ||
| image: phpip:local | ||
| build: | ||
| context: . | ||
| env_file: .env.docker | ||
| environment: | ||
| DB_CONNECTION: mysql | ||
| DB_HOST: db | ||
| DB_PORT: 3306 | ||
| DB_SOCKET: "" | ||
| # MySQL's server-local zone follows APP_TIMEZONE via TZ and SYSTEM. | ||
| DB_TIMEZONE: SYSTEM | ||
| # .env.docker also feeds MySQL initialization; don't pass its root secret to PHP. | ||
| MYSQL_ROOT_PASSWORD: "" | ||
| LOG_CHANNEL: stderr | ||
| CACHE_DRIVER: file | ||
| SESSION_DRIVER: file | ||
| QUEUE_CONNECTION: sync | ||
| volumes: | ||
| - app-storage:/var/www/html/storage | ||
| depends_on: | ||
| db: | ||
| condition: service_healthy | ||
|
|
||
| services: | ||
| app: | ||
| <<: *application | ||
| ports: | ||
| - "${APP_BIND_ADDRESS:-127.0.0.1}:${APP_PORT:-8000}:8080" | ||
| restart: unless-stopped | ||
|
|
||
| scheduler: | ||
| <<: *application | ||
| command: ["scheduler"] | ||
| profiles: ["scheduler"] | ||
| healthcheck: | ||
| disable: true | ||
| restart: unless-stopped | ||
| # The Apache base image uses SIGWINCH; the console worker needs SIGTERM. | ||
| stop_signal: SIGTERM | ||
| stop_grace_period: 60s | ||
|
|
||
| db: | ||
| image: mysql:8.4 | ||
| environment: | ||
|
srdco marked this conversation as resolved.
Resolved
|
||
| TZ: ${APP_TIMEZONE:-UTC} | ||
| MYSQL_DATABASE: ${DB_DATABASE:-phpip} | ||
| MYSQL_USER: ${DB_USERNAME:-phpip} | ||
| MYSQL_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD in .env.docker} | ||
| MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?Set MYSQL_ROOT_PASSWORD in .env.docker} | ||
| command: | ||
| - --default-time-zone=SYSTEM | ||
| - --character-set-server=utf8mb4 | ||
| - --collation-server=utf8mb4_0900_ai_ci | ||
| - --log-bin-trust-function-creators=1 | ||
| # Keep MySQL usable on small test Droplets while retaining stored routines. | ||
| - --innodb-buffer-pool-size=64M | ||
| - --max-connections=20 | ||
| - --performance-schema=OFF | ||
| volumes: | ||
| - db-data:/var/lib/mysql | ||
| healthcheck: | ||
| test: ["CMD-SHELL", "MYSQL_PWD=\"$$MYSQL_PASSWORD\" mysql --protocol=TCP -h 127.0.0.1 -u\"$$MYSQL_USER\" \"$$MYSQL_DATABASE\" -e 'SELECT 1' >/dev/null 2>&1"] | ||
| interval: 5s | ||
| timeout: 5s | ||
| retries: 30 | ||
| start_period: 30s | ||
| restart: unless-stopped | ||
|
|
||
| volumes: | ||
| db-data: | ||
| app-storage: | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| ServerName localhost | ||
| <VirtualHost *:8080> | ||
| DocumentRoot /var/www/html/public | ||
| <Directory /var/www/html/public> | ||
| Options -Indexes +FollowSymLinks | ||
| AllowOverride All | ||
| Require all granted | ||
| </Directory> | ||
| ErrorLog /proc/self/fd/2 | ||
| CustomLog /proc/self/fd/1 combined | ||
| </VirtualHost> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #!/bin/sh | ||
| set -eu | ||
|
|
||
| # Named volumes need these directories on both first boot and subsequent boots. | ||
| if [ "$(id -u)" = 0 ]; then | ||
| mkdir -p storage/app/public storage/app/cache storage/framework/cache/data \ | ||
| storage/framework/sessions storage/framework/views storage/logs bootstrap/cache | ||
| chown -R www-data:www-data storage bootstrap/cache | ||
| fi | ||
|
|
||
| case "${1:-}" in | ||
| apache2-foreground|scheduler) | ||
| if [ -z "${APP_KEY:-}" ]; then | ||
| echo 'Set a persistent APP_KEY in .env.docker before starting phpIP.' >&2 | ||
| exit 1 | ||
| fi | ||
| ;; | ||
| esac | ||
|
|
||
| if [ "${1:-}" = scheduler ]; then | ||
| exec gosu www-data php artisan schedule:work --no-interaction | ||
| fi | ||
|
|
||
| # Run console commands as the web user so shared files stay writable by Apache. | ||
| if [ "${1:-}" = php ] && [ "${2:-}" = artisan ] && [ "$(id -u)" = 0 ]; then | ||
| exec gosu www-data "$@" | ||
| fi | ||
|
|
||
| exec docker-php-entrypoint "$@" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| expose_php = Off | ||
| memory_limit = 256M | ||
| upload_max_filesize = 20M | ||
| post_max_size = 24M | ||
| opcache.enable = 1 | ||
| opcache.validate_timestamps = 0 | ||
| log_errors = On | ||
| error_log = /proc/self/fd/2 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.