Understanding Alpine Linux
Alpine Linux is a security-oriented, lightweight distribution built around musl libc and busybox. Its designed to be minimal, with a standard installation footprint of approximately 120MB. This makes it an ideal base for containerized environments where resource efficiency is paramount.
Benefits for Containerization
While Docker simplifies deployment workflows, large image sizes can hinder transfer speeds and increase storage costs. Utilizing Alpine as the base image significantly reduces the final artifact size, facilitating faster downloads and easier distribution across networks.
Implementation Strategy
Traditional web stacks often employ a full LNMP (Linux, Nginx, MySQL, PHP) setup. However, to adhere to the principle of separated concerns and data persistence, this guide focuses on constructing an image containing only the application runtime: PHP 7.3 and Nginx. Database services should be managed in separate containers.
Creating the Entry Point Script
First, define a bootstrap script to initialize the necessary services when the container starts. Create a file named bootstrap.sh with the following content:
#!/bin/sh
# Ensure runtime directories exist with correct permissions
install -d -m 0755 /var/run/nginx
# Start the web server
/usr/sbin/nginx
# Start the PHP processor
/usr/sbin/php-fpm7
# Keep the container running by following logs
exec tail -f /var/log/nginx/error.log
Constructing the Dockerfile
Place the script in the same directory as your Dockerfile. The following configuration sets up the environment, installs dependencies, creates a non-root user, and cleans up build artifacts to maintain a small image size.
FROM alpine:3.11
COPY bootstrap.sh /
RUN cd / && \
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
apk update && \
apk add --no-cache build-base curl shadow openssh bash libxml2-dev openssl-dev libjpeg-turbo-dev libpng-dev libxpm-dev freetype-dev gd-dev gettext-dev libmcrypt-dev binutils && \
addgroup -S appgroup && \
adduser -S appuser -G appgroup && \
apk add --no-cache nginx && \
apk add --no-cache php7 php7-fpm php7-opcache php7-curl php7-gd php7-mbstring php7-mysqli php7-json php7-mcrypt php7-redis php7-pdo redis && \
apk del build-base shadow binutils && \
chmod +x /bootstrap.sh
EXPOSE 80
ENTRYPOINT ["/bootstrap.sh"]
Building and Running the Image
Execute the build command to create the Docker image. Note that build times may vary depending on network connectivity and package caching.
docker build -t minimal-php-nginx:v1 .
Once the build completes successfully, instantiate a container from the image. The example below names the container production-web and runs it in detached mode.
docker run --name production-web -d minimal-php-nginx:v1
Verify the deployment by inspecting the running processes inside the container. Both the Nginx worker and PHP-FPM processes should be active.
Configuration Management
For flexibility, configuration files should be mounted from the host rather than baked into the image. Map your custom settings to the following paths within the container:
- PHP Configuration:
/etc/php7/php.ini - Nginx Configuration:
/etc/nginx/conf.d/default.conf
When deploying to production environments, ensure specific versions for PHP and Nginx are pinned in the Dockerfile and validated through standard operational security reviews.