Newer
Older
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# ---------------------------------------------- Build Time Arguments --------------------------------------------------
ARG PHP_VERSION="8.2"
ARG PHP_ALPINE_VERSION="3.16"
ARG COMPOSER_VERSION="2"
ARG COMPOSER_AUTH
ARG APP_BASE_DIR="."
# -------------------------------------------------- Composer Image ----------------------------------------------------
FROM composer:${COMPOSER_VERSION} as composer
# ======================================================================================================================
# --- Base ---
# --------------- This stage install needed extenstions, plugins and add all needed configurations -------------------
# ======================================================================================================================
FROM php:${PHP_VERSION}-fpm-alpine${PHP_ALPINE_VERSION} AS base
# Maintainer label
LABEL maintainer="sherifabdlnaby@gmail.com"
# Set SHELL flags for RUN commands to allow -e and pipefail
# Rationale: https://github.com/hadolint/hadolint/wiki/DL4006
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
# ------------------------------------- Install Packages Needed Inside Base Image --------------------------------------
RUN RUNTIME_DEPS="tini fcgi"; \
SECURITY_UPGRADES="curl"; \
apk add --no-cache --upgrade ${RUNTIME_DEPS} ${SECURITY_UPGRADES}
# ---------------------------------------- Install / Enable PHP Extensions ---------------------------------------------
RUN apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
libzip-dev \
icu-dev \
# PHP Extensions --------------------------------- \
&& docker-php-ext-install -j$(nproc) \
intl \
opcache \
zip \
# Pecl Extensions -------------------------------- \
&& pecl install apcu && docker-php-ext-enable apcu \
# Cleanup ---------------------------------------- \
&& rm -r /tmp/pear; \
# - Detect Runtime Dependencies of the installed extensions. \
# - src: https://github.com/docker-library/wordpress/blob/master/latest/php8.0/fpm-alpine/Dockerfile \
out="$(php -r 'exit(0);')"; \
[ -z "$out" ]; err="$(php -r 'exit(0);' 3>&1 1>&2 2>&3)"; \
[ -z "$err" ]; extDir="$(php -r 'echo ini_get("extension_dir");')"; \
[ -d "$extDir" ]; \
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive "$extDir" \
| tr ',' '\n' | sort -u | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
# Save Runtime Deps in a virtual deps
apk add --no-network --virtual .php-extensions-rundeps $runDeps; \
# Uninstall Everything we Installed (minus the runtime Deps)
apk del --no-network .build-deps; \
# check for output like "PHP Warning: PHP Startup: Unable to load dynamic library 'foo' (tried: ...)
err="$(php --version 3>&1 1>&2 2>&3)"; [ -z "$err" ]
# -----------------------------------------------
# Install posgresql
RUN apk add libpq-dev \
&& docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
&& docker-php-ext-install pdo pdo_pgsql pgsql
# Install redis
RUN apk add --no-cache pcre-dev $PHPIZE_DEPS \
&& pecl install redis \
&& docker-php-ext-enable redis
# ------------------------------------------------- Permissions --------------------------------------------------------
# - Clean bundled config/users & recreate them with UID 1000 for docker compatability in dev container.
# - Create composer directories (since we run as non-root later)
# - Add Default Config
RUN deluser --remove-home www-data && adduser -u1000 -D www-data && rm -rf /var/www /usr/local/etc/php-fpm.d/* && \
mkdir -p /var/www/.composer /app && chown -R www-data:www-data /app /var/www/.composer; \
# ------------------------------------------------ PHP Configuration ---------------------------------------------------
mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# Add in Base PHP Config
COPY php/base-* $PHP_INI_DIR/conf.d
# ---------------------------------------------- PHP FPM Configuration -------------------------------------------------
# PHP-FPM config
COPY fpm/*.conf /usr/local/etc/php-fpm.d/
# --------------------------------------------------- Scripts ----------------------------------------------------------
COPY entrypoint/*-base post-build/*-base pre-run/*-base \
fpm/healthcheck-fpm \
scripts/command-loop* \
# to
/usr/local/bin/
RUN chmod +x /usr/local/bin/*-base /usr/local/bin/healthcheck-fpm /usr/local/bin/command-loop*
# ---------------------------------------------------- Composer --------------------------------------------------------
COPY --from=composer /usr/bin/composer /usr/bin/composer
# ----------------------------------------------------- MISC -----------------------------------------------------------
WORKDIR /app
USER www-data
# Common PHP Frameworks Env Variables
ENV APP_ENV prod
ENV APP_DEBUG 0
# Validate FPM config (must use the non-root user)
RUN php-fpm -t
# ---------------------------------------------------- HEALTH ----------------------------------------------------------
HEALTHCHECK CMD ["healthcheck-fpm"]
# -------------------------------------------------- ENTRYPOINT --------------------------------------------------------
ENTRYPOINT ["entrypoint-base"]
CMD ["php-fpm"]
# ======================================================================================================================
# --- Vendor ---
# --------------- This stage will install composer runtime dependinces and install app dependinces. ------------------
# ======================================================================================================================
FROM composer as vendor
ARG PHP_VERSION
ARG COMPOSER_AUTH
ARG APP_BASE_DIR
# A Json Object with remote repository token to clone private Repos with composer
# Reference: https://getcomposer.org/doc/03-cli.md#composer-auth
ENV COMPOSER_AUTH $COMPOSER_AUTH
WORKDIR /app
# Copy Dependencies files
COPY $APP_BASE_DIR/composer.json composer.json
COPY $APP_BASE_DIR/composer.lock composer.lock
# Set PHP Version of the Image
RUN composer config platform.php ${PHP_VERSION}; \
# Install Dependencies
composer install -n --no-progress --ignore-platform-reqs --no-dev --prefer-dist --no-scripts --no-autoloader
# ======================================================================================================================
# ============================================== PRODUCTION IMAGE ====================================================
# --- PROD ---
# ======================================================================================================================
FROM base AS app
ARG APP_BASE_DIR
USER root
# Copy PHP Production Configuration
COPY php/prod-* $PHP_INI_DIR/conf.d/
COPY entrypoint/*-prod post-build/*-prod pre-run/*-prod \
# to
/usr/local/bin/
RUN chmod +x /usr/local/bin/*-prod
USER www-data
# ----------------------------------------------- Production Config -----------------------------------------------------
# Copy Vendor
COPY --chown=www-data:www-data --from=vendor /app/vendor /app/vendor
# Copy App Code
COPY --chown=www-data:www-data $APP_BASE_DIR/ .
## Run Composer Install again
## ( this time to run post-install scripts, autoloader, and post-autoload scripts using one command )
RUN composer install --optimize-autoloader --apcu-autoloader --no-dev -n --no-progress && \
composer check-platform-reqs && \
post-build-base && post-build-prod
ENTRYPOINT ["entrypoint-prod"]
CMD ["php-fpm"]
# ======================================================================================================================
# ============================================== DEVELOPMENT IMAGE ===================================================
# --- DEV ---
# ======================================================================================================================
FROM base as app-dev
ENV APP_ENV dev
ENV APP_DEBUG 1
# Switch root to install stuff
USER root
# For Composer Installs
RUN apk --no-cache add git openssh bash
# ---------------------------------------------------- Scripts ---------------------------------------------------------
# Copy Dev Scripts
COPY php/dev-* $PHP_INI_DIR/conf.d/
COPY entrypoint/*-dev post-build/*-dev pre-run/*-dev \
# to
/usr/local/bin/
RUN chmod +x /usr/local/bin/*-dev; \
mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
USER www-data
# ------------------------------------------------- Entry Point --------------------------------------------------------
# Entrypoints
ENTRYPOINT ["entrypoint-dev"]
CMD ["php-fpm"]