-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathDockerfile.fly
More file actions
164 lines (131 loc) · 7.59 KB
/
Dockerfile.fly
File metadata and controls
164 lines (131 loc) · 7.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# =============================================================================
# Stage 1: Build assets (Node + Composer)
# =============================================================================
FROM php:8.2-cli AS builder
# Install system dependencies for building
RUN apt-get update && apt-get install -y --no-install-recommends \
git zip unzip curl \
libpng-dev libjpeg62-turbo-dev libfreetype6-dev libzip-dev libicu-dev libxml2-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql bcmath zip intl gd exif \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Install xmlrpc via pecl
RUN pecl install channel://pecl.php.net/xmlrpc-1.0.0RC3 && docker-php-ext-enable xmlrpc
# Install composer
COPY --from=composer/composer:2-bin /composer /usr/bin/composer
# Install Node 18
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y nodejs \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /build
# Copy composer files first for layer caching
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
# Copy package files for npm layer caching
COPY package.json package-lock.json ./
RUN npm ci --legacy-peer-deps
RUN NPM_CONFIG_LEGACY_PEER_DEPS=true npx update-browserslist-db@latest
# Copy all source code
COPY . .
# Create a minimal .env for artisan commands during build (no DB needed)
RUN echo "APP_KEY=base64:$(openssl rand -base64 32)" > .env && \
echo "APP_ENV=production" >> .env
# Finish composer autoload (skip post-autoload scripts that need DB/app context)
ENV COMPOSER_ALLOW_SUPERUSER=1
RUN composer dump-autoload --optimize --no-dev --no-scripts
# Run package discovery manually
RUN php artisan package:discover --ansi || true
# Build frontend assets
# The webpack.mix.js runs `php artisan lang:js` via WebpackShellPlugin, but that
# needs the full app bootstrapped. Generate translations first, then build.
RUN php artisan lang:js --no-lib resources/js/translations.js 2>/dev/null || true
RUN npm run production && rm -f public/hot
# Generate swagger docs (non-fatal if it fails)
RUN php artisan l5-swagger:generate 2>/dev/null || true
# Remove build .env (real env comes from Fly secrets at runtime)
RUN rm -f .env
# =============================================================================
# Stage 2: Production image (Nginx + PHP-FPM + Supervisord + Cron)
# =============================================================================
FROM php:8.2-fpm
# yesterday mode adds mariadb-server (co-located DB for restored snapshots).
ARG STARTUP_SCRIPT=startup.sh
RUN apt-get update && apt-get install -y --no-install-recommends \
nginx \
supervisor \
cron \
gettext-base \
redis-server \
procps \
default-mysql-client \
rclone \
libpng-dev libjpeg62-turbo-dev libfreetype6-dev libzip-dev libicu-dev libxml2-dev \
&& if [ "$STARTUP_SCRIPT" = "yesterday-startup.sh" ]; then apt-get install -y --no-install-recommends default-mysql-server; fi \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql bcmath zip intl gd exif pcntl \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Install xmlrpc
RUN pecl install channel://pecl.php.net/xmlrpc-1.0.0RC3 && docker-php-ext-enable xmlrpc
# Configure PHP-FPM to use unix socket.
# The base image ships docker.conf (formerly zz-docker.conf) with:
# listen = 9000 — overrides www.conf (last-file-wins in glob)
# clear_env = no — lets Fly.io env vars reach PHP workers (must keep)
# We patch docker.conf: keep clear_env=no, switch listen to unix socket.
# www.conf has no bare `listen =` line, so we append one there as belt-and-braces.
RUN sed -i 's|^listen = .*|listen = /var/run/php-fpm.sock|' /usr/local/etc/php-fpm.d/docker.conf && \
rm -f /usr/local/etc/php-fpm.d/zz-docker.conf && \
sed -i 's|;listen.owner = www-data|listen.owner = www-data|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|;listen.group = www-data|listen.group = www-data|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|;listen.mode = 0660|listen.mode = 0660|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|;slowlog = .*|slowlog = /var/log/php-fpm-slow.log|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|;request_slowlog_timeout = .*|request_slowlog_timeout = 5s|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|;request_terminate_timeout = .*|request_terminate_timeout = 120s|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|pm.max_children = [0-9]*|pm.max_children = 200|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|pm.start_servers = [0-9]*|pm.start_servers = 20|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|pm.min_spare_servers = [0-9]*|pm.min_spare_servers = 10|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|pm.max_spare_servers = [0-9]*|pm.max_spare_servers = 50|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|;pm.status_path = .*|pm.status_path = /fpm-status|' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's|;pm.status_listen = .*|pm.status_listen = 127.0.0.1:9001|' /usr/local/etc/php-fpm.d/www.conf
# Install sysstat (sar), vim, procps (vmstat) and iputils-ping for diagnostics
RUN apt-get update && apt-get install -y --no-install-recommends sysstat vim-tiny procps iputils-ping && \
sed -i 's/ENABLED="false"/ENABLED="true"/' /etc/default/sysstat && \
rm -rf /var/lib/apt/lists/*
# PHP production settings
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/conf.d/php.ini && \
echo "upload_max_filesize = 100M" >> /usr/local/etc/php/conf.d/php.ini && \
echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/php.ini && \
echo "memory_limit = 1024M" >> /usr/local/etc/php/conf.d/php.ini && \
echo "max_execution_time = 120" >> /usr/local/etc/php/conf.d/php.ini
# Copy nginx config
COPY docker/nginx-fly.conf /etc/nginx/nginx.conf
# Copy supervisord config
COPY docker/supervisord-fly.conf /etc/supervisor/conf.d/supervisord.conf
# Copy logrotate config
COPY docker/logrotate-fly.conf /etc/logrotate.d/restarters
# Copy queue watchdog
COPY docker/queue-watchdog.sh /usr/local/bin/queue-watchdog.sh
RUN chmod +x /usr/local/bin/queue-watchdog.sh
# Copy database backup script and yesterday restart script
COPY docker/db-backup.sh /usr/local/bin/db-backup.sh
COPY docker/restart-yesterday.sh /usr/local/bin/restart-yesterday.sh
RUN chmod +x /usr/local/bin/db-backup.sh /usr/local/bin/restart-yesterday.sh
# Set up cron: Laravel scheduler + queue watchdog + hourly DB backup + daily yesterday restart (5am UTC)
RUN printf '* * * * * cd /var/www && php artisan schedule:run >> /dev/null 2>&1\n* * * * * /usr/local/bin/queue-watchdog.sh\n0 * * * * /usr/local/bin/db-backup.sh\n0 5 * * * /usr/local/bin/restart-yesterday.sh\n' | crontab -
# Set working directory
WORKDIR /var/www
# Copy application from builder
COPY --from=builder --chown=www-data:www-data /build /var/www
# Remove dev files not needed in production
RUN rm -rf node_modules tests .git .github
# Ensure storage and cache directories exist
RUN mkdir -p storage/framework/{sessions,views,cache/data} \
storage/logs bootstrap/cache \
public/uploads \
&& chown -R www-data:www-data storage bootstrap/cache public/uploads
# Copy startup scripts (production + yesterday-restore variant)
COPY .fly/scripts/startup.sh /usr/local/bin/startup.sh
COPY docker/yesterday-startup.sh /usr/local/bin/yesterday-startup.sh
RUN chmod +x /usr/local/bin/startup.sh /usr/local/bin/yesterday-startup.sh && \
cp /usr/local/bin/${STARTUP_SCRIPT} /usr/local/bin/active-startup.sh
EXPOSE 80
CMD ["/usr/local/bin/active-startup.sh"]