1. Xây dựng small container Nginx + PHP-FPM với Alpine Linux
Ưu điểm: xây dựng nhanh chóng dễ dàng, tạo ra Image <= 100MB, dễ cấu hình và cài đặt thêm.
Nhược điểm: phụ thuộc vào gói cài đặt Alpine Linux mà được cung cấp các gói cài thành phần phụ thuộc. Đây là nhược điểm nhưng cũng là ưu điểm, tạo ra image với độ ổn định cao, các gói cài đặt phù hợp.
Bài viết làm dựa trên eXistenZNL. Hiện đang hỗ trợ các phiên bản PHP-FPM 8.1, PHP-FPM 8.2, PHP-FPM 8.3. Bài viết sẽ làm demo phiên bản cũ hơn là PHP-FPM 7.4.
Dự án tạo được lưu trữ trên dylanbui Github
Tìm hiểu Alpine Linux và các câu lệnh
Alpine Linux là bản phân phối Linux dựa trên musl và BusyBox, được thiết kế bảo mật, đơn giản và hiệu quả về tài nguyên. Nó sử dụng OpenRC cho hệ thống init. Alpine nổi lên sau khi Docker được phát triển bởi vì nó nhỏ và nhẹ, thường được sử dụng để làm docker image.
Giống như các distro Linux khác, Alpine sử dụng repo để cài đặt và cập nhật gói theo các phiên bản của Alpine. Các phiên bản ổn định của Alpine được đánh tên theo số ví dụ 3.13 3.12
Tìm hiểu chi tiết tại dao-choi-voi-alpine-linux
Quản lý gói trên Alpine Linux
Để tìm kiếm gói hỗ trợ vào trang sau alpinelinux packages
- Cài đặt gói:
apk add <tên gói> - Gỡ bỏ gói:
apk del <tên gói> - Khởi chạy một chương trình:
rc-service <tên chương trình> start - Dừng chương trình đang chạy
rc-service <tên chương trình> stop - Khởi động chương trình cùng hệ thống
rc-update add <tên chương trình> - Xóa khởi động chương trình cùng hệ thống
rc-update del <tên chương trình> - Cài đặt gói chỉ định
apk add <tên gói>@<tên repo> - Cài đặt gói theo phiên bản cụ thể
apk add <tên gói>==<phiên bản>Ex: apk add bash==4.3.33-r0
Quản lý gói trên Alpine-Linux bỏ rơi những gói cũ khi chúng có những phiên bản mới hơn. Đôi khi bạn cần phải cài đặt gói cũ trên phiên bản Alpine mới, câu lệnh được thực hiện tương tự như sau cho việc cài đặt nodejs 12 cũ trên Alpine 3.13 mới hơn.
apk add --no-cache --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.12/main nodejs==12.22.1-r0
- Tùy chọn
--no-cacheyêu cầu ko lưu lại file cài đặt. Điều này sẽ làm cho Phiên bản Alpine Linux sau khi tạo ra sẽ có dung lượng nhẹ hơn.
Timezone trên Alpine Linux
# Trên Alpine timezone package không được cài mặc định, do đó bạn cần phải cài đặt nó trước khi thiết lập timezone.
apk update
apk add --no-cache tzdata
# Liệt kê các timezone
ls /usr/share/zoneinfo
# Ví dụ set timezone Ho Chi Minh
ln -fs /usr/share/zoneinfo/Asia/Ho_Chi_Minh /etc/localtime
Cài đặt Bash Shell + Login Root
apk add --no-cache bash
Sau khi cài đặt xong Alpine Linux bạn không thể login SSH với tài khoản root vì Alpine mặc định không cho login bằng tài khoản root, do đó bạn phải chỉnh sửa file cấu hình ssh để cho phép login với tài khoản root:
vi /etc/ssh/sshd_config
Tìm đến dòng sau và sửa thành:
PermitRootLogin yes
Xây dựng Image Nginx + PHP-FPM7 với Alpine Linux 3.13
Cấu trúc thư mục Image và cài đặt
Cấu trúc thư mục lưu file dành cho Image. Toàn bộ được lưu trong webstack dylanbui Github
root
|-- files
|-- general
|-- etc
|-- nginx
|-- nginx.conf
|-- services.d
|-- nginx
|-- finish
|-- run
|-- www
|-- public
|-- index.php
|-- php7
|-- etc
|-- php7
|-- php-fpm.conf
|-- services.d
|-- php-fpm7
|-- finish
|-- run
|
| Dockerfle
# Sử dụng phiên bản stable 3.13
# Ở đây ta chỉ build phiên bản đầy đủ cho dung lượng nhỏ <= 50MB
# Các thành phần cần cho build php tùy theo project sẽ build trong layer image cần
# Name: web-stack-php8:1.0
FROM alpine:3.13.12
LABEL maintainer="buivantienduc@gmail.com"
LABEL description="Lightweight container with Nginx & PHP 7.4 based on Alpine Linux."
# Install webserver packages, cần gói php hỗ trợ thì thêm vào
RUN apk -U upgrade && apk add --no-cache \
curl \
nginx \
php7-fpm php7-json php7-gd php7-pdo_mysql \
tzdata \
&& ln -s /usr/sbin/php-fpm7 /usr/sbin/php-fpm \
&& addgroup -S php \
&& adduser -S -G php php \
&& rm -rf /var/cache/apk/* /etc/nginx/http.d/* /etc/php7/conf.d/* /etc/php7/php-fpm.d/*
# Install S6 overlay only linux/amd64
# Sử dụng S6 để quản lý các service chạy, cụ thể ở đây là nginx, php-fpm
ARG S6_OVERLAY_VERSION=2.2.0.3
RUN wget -P /tmp https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-amd64.tar.gz && \
gunzip -c /tmp/s6-overlay-amd64.tar.gz | tar -xf - -C / && \
rm -rf /tmp/*
COPY files/general files/php7 /
WORKDIR /www
ENTRYPOINT ["/init"]
EXPOSE 80
HEALTHCHECK --interval=5s --timeout=5s CMD curl -f http://127.0.0.1/php-fpm-ping || exit 1
# -- Build
docker build -t web-stack-php8:1.0 --force-rm -f 7.Dockerfile .
# -- Chạy container test
docker run -it --name webstack-7 -p 8888:80 web-stack-php8:1.0
Sử dụng để buidl các phiên bản Image tùy vào từng Project
FROM web-stack-php8:1.0
# -- Add bash nếu cần login
RUN apk -U --no-cache add bash
# -- Add composer, npm, nodejs nếu cần
RUN apk -U --no-cache add \
git \
composer \
npm \
nodejs
# -- Cài đặt gói php
RUN apk -U --no-cache add \
php83-ctype \
php83-mbstring
# -- Change timezone
RUN ln -fs /usr/share/zoneinfo/Asia/Ho_Chi_Minh /etc/localtime
# -- Clone source code từ git vào thư mục /www. Nên sử dụng access token cho git account
RUN rm -rf /www && \
git clone [git reposetory] /www && \
chown -R php:nginx /www
# -- OR copy file từ thư mục host
COPY --chown=php:nginx src/ /www
# -- Nếu sử dụng Laveral thì cần trỏ lại nginx.conf vào thư mục /www/public_html
# WORKDIR /www/public_html
# RUN composer install && npm install
# -- Tìm kiếm các file set giá trị chmod
RUN find /www -type d -exec chmod -R 555 {} \; \
&& find /www -type f -exec chmod -R 444 {} \; \
&& find /www/var -type d -exec chmod -R 755 {} \; \
&& find /www/var -type f -exec chmod -R 644 {} \;
Thay đổi file cấu hình Nginx, PHP-FPM, htdocs
- Nginx chạy dưới người dùng nginx của hệ thống và PHP-FPM chạy dưới người dùng php của hệ thống.
- Source code được copy vào /www, vì đây là thư mục mặc định mà Nginx và PHP hoạt động trong container.
- Nếu cài đặt CMS hoặc framework như Laravel / Symfony / WordPress có thư mục public, thì copy vào /www/public và thay đổi root directory trong file nginx.conf.
| Application | Copy files into this directory | Overwrite this file if needed |
|---|---|---|
| PHP core directives (7.4) | /etc/php7/conf.d/ | /etc/php7/php.ini |
| PHP-FPM (7.4) | /etc/php7/php-fpm.d/ | /etc/php7/php-fpm.conf |
| PHP core directives (8.1) | /etc/php81/conf.d/ | /etc/php81/php.ini |
| PHP-FPM (8.1) | /etc/php81/php-fpm.d/ | /etc/php81/php-fpm.conf |
| PHP core directives (8.2) | /etc/php82/conf.d/ | /etc/php82/php.ini |
| PHP-FPM (8.2) | /etc/php82/php-fpm.d/ | /etc/php82/php-fpm.conf |
| PHP core directives (8.3) | /etc/php83/conf.d/ | /etc/php83/php.ini |
| PHP-FPM (8.3) | /etc/php83/php-fpm.d/ | /etc/php83/php-fpm.conf |
| Nginx | /etc/nginx/conf.d/ | /etc/nginx/nginx.conf |
Các dự án cùng ý tưởng, tham khảo
Phiên bản chi tiết build từng loại Alpine tương ứng với PHP, Nginx
TrafeX-docker-php-nginx(Tạm được), PrivateBin-docker-nginx-fpm-alpine(cấu hình lung tung, để tham khảo)
Bài viết hướng dẫn từ đầu, thấy hay
2. Xây dựng small container sử dụng PHP:x.x-fpm-alpine, cài đặt Nginx với các Modules cần thiết
Giải pháp này cũng gần giống dùng Alpine Linux, nó chỉ dùng 1 phiên bản Alpine Linux đã cài sẵn PHP và chúng ta sẽ cài những phần còn lại. Ta sẽ sử dụng php:[PHP_VERSION]-fpm-alpine đã cài sẵn PHP ta chỉ cần install thêm Nginx hay Apache cùng các modules cần thiết tùy theo nhu cầu.
- Ưu điểm: dễ cài đặt hơn, tùy chọn gói PHP version cần thiết.
- Nhược điểm: phiên bản cài đặt lớn hơn <= 200MB. Khi chạy nó sẽ lắng nghe thêm cổng 9000 (mặc định) của php-fpm
Các thư mục cấu hình khi cài đặt PHP:xx-fpm-alpine
/usr/local/etc/phpthư mục cấu hình php trong này có file php.ini thư mục con conf.d để import file .ini./usr/local/etc/php/php.ini/usr/local/etc/php/conf.d/usr/local/etc/php-fpm.conffile cấu hình cho php-fpm./usr/local/etc/php-fpm.dfile import override cấu hình cho php-fpm./etc/nginx/nginx.conffile cấu hình Nginx server/etc/nginx/conf.dfile import override cấu hình cho Nginx./usr/local/sbin/php-fpmfile start php-fpm service./usr/sbin/nginxfile start Nginx service/www/public_htmlthư mục được cấu hình root trong Nginx chạy index.php.www-data:nginxuser:group dùng cho php-fpm:nginx
Phiên bản sử dụng S6 trực tiếp để khởi chạy các services Nginx, PHP-FPM - Source Code
# Chọn PHP version
ARG PHP_VERSION=7.4
ARG GD="--with-png-dir=/usr/lib/ --with-jpeg-dir=/usr/lib/ --with-gd"
FROM php:${PHP_VERSION}-fpm-alpine
############################################################################################
# PHP #
############################################################################################
RUN mkdir -p /usr/share/man/man1 /usr/share/man/man7 && \
apk add --update --no-cache --virtual .build-deps icu-dev jpeg-dev libjpeg-turbo-dev libpng-dev libzip-dev postgresql-dev tzdata autoconf alpine-sdk linux-headers && \
apk --no-cache add postgresql-client libpq libpng libjpeg icu-libs libzip tzdata bash curl git && \
pecl channel-update pecl.php.net && \
# Install php module
pecl install redis && docker-php-ext-enable redis && \
docker-php-ext-configure gd ${GD} && \
docker-php-ext-install bcmath exif gd intl mysqli opcache pcntl pdo pdo_mysql pdo_pgsql pgsql sockets zip && \
apk del .build-deps && \
rm -rf /usr/src && \
mv "${PHP_INI_DIR}/php.ini-production" "${PHP_INI_DIR}/php.ini"
COPY php/limits.ini ${PHP_INI_DIR}/conf.d/
############################################################################################
# NGINX
############################################################################################
RUN set -x \
&& addgroup -g 101 -S nginx \
&& adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \
&& apk add --no-cache nginx \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
############################################################################################
# COMPOSE
############################################################################################
RUN apk --no-cache add npm nodejs
# Install the latest version of Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
############################################################################################
# Set timezone (can goi tzdata o trên)
############################################################################################
RUN cp /usr/share/zoneinfo/Asia/Ho_Chi_Minh /etc/localtime && \
echo "Asia/Ho_Chi_Minh" > /etc/timezone
############################################################################################
# supervisor (quản lý chạy các service) có the install truc tiep tu apk add supervisor
############################################################################################
# Install S6 overlay only linux/amd64
ARG S6_OVERLAY_VERSION=2.2.0.3
RUN wget -P /tmp https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-amd64.tar.gz && \
gunzip -c /tmp/s6-overlay-amd64.tar.gz | tar -xf - -C / && \
rm -rf /usr/src && rm -rf /tmp/*
COPY general /
# User www-data:nginx
WORKDIR /www
EXPOSE 80
# File mac dinh chay supervisor
CMD ["/init"]
Phiên bản sử dụng một file star.sh để gọi khởi chạy service S6. Ta có thể thêm câu lệnh vào file star.sh này (như là pull code từ git, build theo ENV) - Source Code
Trong version này ta có dùng câu lệnh sed để thay đổi nội dụng file cấu hình theo nhu cầu.
ARG GD="--with-png-dir=/usr/lib/ --with-jpeg-dir=/usr/lib/ --with-gd"
FROM php:7.4-fpm-alpine
LABEL maintainer="Bui Van Tien Duc <buivantienduc@gmail.com>"
# ENV php_conf /usr/local/etc/php-fpm.conf
ENV fpm_conf /usr/local/etc/php-fpm.d/www.conf
# ENV php_vars /usr/local/etc/php/conf.d/docker-vars.ini
############################################################################################
# PHP
############################################################################################
RUN mkdir -p /usr/share/man/man1 /usr/share/man/man7 && \
apk add --update --no-cache --virtual .build-deps icu-dev jpeg-dev libjpeg-turbo-dev libpng-dev libzip-dev postgresql-dev tzdata autoconf alpine-sdk linux-headers && \
apk --no-cache add postgresql-client libpq libpng libjpeg icu-libs libzip tzdata bash curl git supervisor && \
pecl channel-update pecl.php.net && \
# Install php module
pecl install redis && docker-php-ext-enable redis && \
docker-php-ext-configure gd ${GD} && \
docker-php-ext-install bcmath exif gd intl mysqli opcache pcntl pdo pdo_mysql pdo_pgsql pgsql sockets zip && \
apk del .build-deps && \
rm -rf /usr/src && \
mv "${PHP_INI_DIR}/php.ini-production" "${PHP_INI_DIR}/php.ini"
COPY files/etc/php/conf.d/limits.ini ${PHP_INI_DIR}/conf.d/
############################################################################################
# NGINX
############################################################################################
RUN set -x \
&& addgroup -g 101 -S nginx \
&& adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \
&& apk add --no-cache nginx \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
COPY files/etc/nginx/nginx.conf /etc/nginx/nginx.conf
COPY files/etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
############################################################################################
# Tweak php-fpm config
############################################################################################
# tweak php-fpm config
# RUN echo "cgi.fix_pathinfo=0" > ${php_vars} &&\
# echo "upload_max_filesize = 100M" >> ${php_vars} &&\
# echo "post_max_size = 100M" >> ${php_vars} &&\
# echo "variables_order = \"EGPCS\"" >> ${php_vars} && \
# echo "memory_limit = 128M" >> ${php_vars} && \
RUN sed -i \
-e "s/;catch_workers_output\s*=\s*yes/catch_workers_output = yes/g" \
-e "s/pm.max_children = 5/pm.max_children = 4/g" \
-e "s/pm.start_servers = 2/pm.start_servers = 3/g" \
-e "s/pm.min_spare_servers = 1/pm.min_spare_servers = 2/g" \
-e "s/pm.max_spare_servers = 3/pm.max_spare_servers = 4/g" \
-e "s/;pm.max_requests = 500/pm.max_requests = 200/g" \
-e "s/user = www-data/user = nginx/g" \
-e "s/group = www-data/group = nginx/g" \
-e "s/;listen.mode = 0660/listen.mode = 0666/g" \
-e "s/;listen.owner = www-data/listen.owner = nginx/g" \
-e "s/;listen.group = www-data/listen.group = nginx/g" \
-e "s/listen = 127.0.0.1:9000/listen = \/var\/run\/php-fpm.sock/g" \
-e "s/^;clear_env = no$/clear_env = no/" \
${fpm_conf}
############################################################################################
# COMPOSE
############################################################################################
RUN apk --no-cache add npm nodejs
# Install the latest version of Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
############################################################################################
# Set timezone
############################################################################################
RUN cp /usr/share/zoneinfo/Asia/Ho_Chi_Minh /etc/localtime && \
echo "Asia/Ho_Chi_Minh" > /etc/timezone
############################################################################################
# supervisor (chi can add file cau hinh). apk add supervisor
############################################################################################
ADD files/etc/supervisord.conf /etc/supervisord.conf
# Clear cache files
RUN rm -rf /usr/src && rm -rf /tmp/*
ADD files/start.sh /start.sh
RUN chmod 755 /start.sh
RUN mkdir -p /var/www
# copy in code
COPY src /var/www
EXPOSE 80
# User www-data:nginx
WORKDIR /var/www
CMD ["/start.sh"]
#!/bin/bash
# Demo su dung file
# https://github.com/richarvey/nginx-php-fpm/blob/main/scripts/start.sh
# Start supervisord and services
exec /usr/bin/supervisord -n -c /etc/supervisord.conf
3. Xây dựng small container simple PHP + Apache với Alpine Linux
Hệ thống đơn giản hơn, không nhiều cấu hình. Build PHP8 + Apache from Alpine
Tham khảo từ các hệ thống
Bài viết
laravel-applications-with-docker
containerizing-nginx-php-fpm-on-alpine-linux
Đã xây dựng thực thế dùng cho CI/CD (tham khảo chủ yếu ở đây cho webstack)
Xây dựng đầy đủ và chi tiết nhất
Cấu hình dùng file start.sh, với nhiều option khi build
Đơn giản dễ hiểu nhưng cần được cấu hình lại kết hợp với joseluisq mới có thể chạy tốt
corbosman-nginx-php (Đang chủ yếu dùng thằng này, nhưng quản lý service thì dùng của thằng khác)
Justintime50 source này như trên nhưng được cái tham khảo thêm cấu hình email
Ý tưởng build một con php:7.4-alpine với các phần mởi rộng, chạy php trên cổng 9000, share thư mục /var/www ra dùng chung với các server Nginx, Apache. Một server php-fpm:9000 sẽ thông dịch toàn bộ php files cho nhiều con server Nginx, Apache - Cần được đánh giá performance
https://varlock.net/how-to-run-nginx-and-php-in-docker/