algo que eu posso colocar em produção
Não é recomendado colocar npm run dev
em produção, já que ele expõe todos os seus sourcemaps e gera um overhead gigantesco por ter que verificar toda hora se os arquivos foram alterados.
Sendo assim a instalação do node poderia estar em um container totalmente separado, apenas para desenvolvimento.
Outro motivo para usar configurações separadas é a otimização de produção. O PHP precisa ficar alterando o tempo inteiro? Não, então deixa tudo compilado e quando alterar rebuilda a imagem inteira
Aqui vai uma ideia do que uso nos meus projetos em produção. Eu crio uma configuração totalmente personalizada para cada projeto, é uma boa base para começar.
Dockerfile
############ BUILD PHP #############
FROM php:8.3-fpm AS build-php
WORKDIR /app
RUN apt update && \
apt install -y ca-certificates curl tar libxml2-dev libzip-dev wget libpq-dev && \
apt clean
RUN docker-php-ext-install opcache
RUN docker-php-ext-configure zip
RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql
RUN docker-php-ext-install bcmath pdo_mysql zip xml sockets pgsql pdo_pgsql intl
RUN pecl install redis && docker-php-ext-enable redis
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY . ./
RUN composer install --optimize-autoloader --no-dev
RUN cp /app/deploy/php.ini /usr/local/etc/php/conf.d/z_config.ini
########### STATIC BUILD ###########
FROM node:20-alpine AS static-build
WORKDIR /app
COPY package.json ./
RUN npm install --include=dev
COPY . ./
RUN npm run build
############### BASE ###############
FROM build-php AS base
COPY --from=static-build /app/public/build /app/public/build
########## STATIC SERVER ###########
FROM nginx:alpine AS static-server
WORKDIR /app/public
COPY ./deploy/static/nginx.conf /etc/nginx/nginx.conf
COPY ./deploy/static/static.conf /etc/nginx/conf.d/default.conf
COPY --from=static-build /app/public /app/public
############ WEB SERVER ############
FROM base AS web
RUN chmod +x deploy/web/docker_entrypoint.sh
########## WORKER SERVER ###########
FROM base AS worker
RUN apt update && apt install -y supervisor && apt clean
RUN chmod +x deploy/worker/docker_entrypoint.sh
# Config workers
RUN cp /app/deploy/worker/* /etc/supervisor/conf.d/ && \
touch /app/storage/logs/schedule.log && \
touch /app/storage/logs/worker.log
Docker compose
services:
web:
restart: always
build:
context: .
target: web
entrypoint: 'deploy/web/docker_entrypoint.sh'
volumes:
- ./storage:/app/storage
ports:
- 9000:9000
env_file:
- .env
networks:
- [appname]svc
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.25'
memory: 256M
worker:
restart: always
build:
context: .
target: worker
entrypoint: 'deploy/worker/docker_entrypoint.sh'
volumes:
- ./storage:/app/storage
env_file:
- .env
networks:
- [appname]svc
deploy:
resources:
limits:
cpus: '1'
memory: 1.5G
reservations:
memory: 256M
static:
restart: always
build:
context: .
target: static-server
ports:
- 9001:9001
networks:
- [appname]svc
deploy:
resources:
limits:
cpus: '1'
memory: 128M
reservations:
cpus: '0.25'
memory: 32M
networks:
[appname]svc:
driver: bridge
external: true
name: [appname]_svc
static.conf
server {
root /app/public;
listen [::]:9001;
listen 9001;
}
Sim, tem um nginx dedicado a apenas servir os estáticos deste projeto, e outro nginx para fazer o proxy de todos os serviços
entrypoint web
#!/bin/bash
php artisan migrate --force --isolated
php artisan db:seed --force
php artisan optimize:clear
php artisan optimize
php-fpm
entrypoint worker
#!/bin/bash
php artisan migrate --force --isolated
php artisan optimize:clear
php artisan optimize
supervisord -n
Conf supervisor worker
[program:[appname]-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /app/artisan queue:work --max-jobs=1000 --max-time=3600 --queue=high,default,low
autostart=true
autorestart=true
stopasgroup=true
numprocs=10
redirect_stderr=true
stdout_logfile=/app/storage/logs/worker.log
stopwaitsecs=30
user=www-data
[program:[appname]-schedule]
process_name=%(program_name)s_%(process_num)02d
command=php /app/artisan schedule:work
autostart=true
autorestart=true
stopasgroup=true
numprocs=1
redirect_stderr=true
stdout_logfile=/app/storage/logs/schedule.log
user=www-data
nginx conf
server {
server_name [appname];
root /app;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app/public/index.php;
}
location /build {
proxy_pass http://127.0.0.1:9001;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
listen [::]:443 ssl;