feat(docker): add production docker-compose for Coolify deployment
Coolify builds with --project-directory set to the repo root, which broke the dev compose file's relative paths. Adds a dedicated prod compose stack (baked-in code, no bind mounts, no hardcoded secrets, static Nuxt build served by nginx) so local dev and Coolify no longer share fragile path assumptions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
71730fef06
commit
a95fac5c0d
6 changed files with 143 additions and 1 deletions
11
Makefile
11
Makefile
|
|
@ -1,4 +1,4 @@
|
||||||
PHONY: dev stop test lint migrate fresh shell-php shell-node build
|
PHONY: dev stop test lint migrate fresh shell-php shell-node build prod-build prod-up prod-stop
|
||||||
|
|
||||||
dev:
|
dev:
|
||||||
docker compose -f docker/docker-compose.yml up -d
|
docker compose -f docker/docker-compose.yml up -d
|
||||||
|
|
@ -26,3 +26,12 @@ shell-node:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
docker compose -f docker/docker-compose.yml exec frontend npm run build
|
docker compose -f docker/docker-compose.yml exec frontend npm run build
|
||||||
|
|
||||||
|
prod-build:
|
||||||
|
docker compose -f docker/docker-compose.prod.yml --project-directory . build
|
||||||
|
|
||||||
|
prod-up:
|
||||||
|
docker compose -f docker/docker-compose.prod.yml --project-directory . up -d
|
||||||
|
|
||||||
|
prod-stop:
|
||||||
|
docker compose -f docker/docker-compose.prod.yml --project-directory . down
|
||||||
|
|
|
||||||
55
docker/docker-compose.prod.yml
Normal file
55
docker/docker-compose.prod.yml
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: docker/php/Dockerfile.prod
|
||||||
|
environment:
|
||||||
|
APP_ENV: production
|
||||||
|
APP_DEBUG: "false"
|
||||||
|
APP_KEY: ${APP_KEY}
|
||||||
|
APP_URL: ${APP_URL}
|
||||||
|
DB_HOST: mysql
|
||||||
|
DB_DATABASE: ${DB_DATABASE}
|
||||||
|
DB_USERNAME: ${DB_USERNAME}
|
||||||
|
DB_PASSWORD: ${DB_PASSWORD}
|
||||||
|
RUN_MIGRATIONS: "true"
|
||||||
|
depends_on:
|
||||||
|
mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- mandant
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: docker/frontend/Dockerfile.prod
|
||||||
|
ports:
|
||||||
|
- "8899:80"
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- mandant
|
||||||
|
|
||||||
|
mysql:
|
||||||
|
image: mysql:8.0
|
||||||
|
environment:
|
||||||
|
MYSQL_DATABASE: ${DB_DATABASE}
|
||||||
|
MYSQL_USER: ${DB_USERNAME}
|
||||||
|
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- mysql_data:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
networks:
|
||||||
|
- mandant
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
mandant:
|
||||||
|
driver: bridge
|
||||||
14
docker/frontend/Dockerfile.prod
Normal file
14
docker/frontend/Dockerfile.prod
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
FROM node:20-alpine AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY frontend/package.json frontend/package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY frontend/ .
|
||||||
|
RUN npm run generate
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
COPY --from=build /app/.output/public /usr/share/nginx/html
|
||||||
|
COPY docker/nginx/default.prod.conf /etc/nginx/conf.d/default.conf
|
||||||
25
docker/nginx/default.prod.conf
Normal file
25
docker/nginx/default.prod.conf
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
client_max_body_size 10M;
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://backend:8000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /sanctum/ {
|
||||||
|
proxy_pass http://backend:8000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
docker/php/Dockerfile.prod
Normal file
26
docker/php/Dockerfile.prod
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
FROM php:8.2-cli-alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
libpng-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
zip \
|
||||||
|
unzip \
|
||||||
|
git \
|
||||||
|
sqlite-dev \
|
||||||
|
&& docker-php-ext-install pdo pdo_mysql pdo_sqlite gd
|
||||||
|
|
||||||
|
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
|
COPY backend/ /var/www/html
|
||||||
|
COPY docker/php/entrypoint.prod.sh /entrypoint.sh
|
||||||
|
|
||||||
|
RUN composer install --no-dev --optimize-autoloader --no-interaction \
|
||||||
|
&& chmod +x /entrypoint.sh \
|
||||||
|
&& chown -R www-data:www-data storage bootstrap/cache
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
13
docker/php/entrypoint.prod.sh
Normal file
13
docker/php/entrypoint.prod.sh
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
php artisan storage:link || true
|
||||||
|
php artisan config:cache
|
||||||
|
php artisan route:cache
|
||||||
|
php artisan view:cache
|
||||||
|
|
||||||
|
if [ "$RUN_MIGRATIONS" = "true" ]; then
|
||||||
|
php artisan migrate --force
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec php artisan serve --host=0.0.0.0 --port=8000
|
||||||
Loading…
Reference in a new issue