Docker For Local Web Development, Part 2 - Put Your Images On A Diet
Docker For Local Web Development, Part 2 - Put Your Images On A Diet
In this post
In this series
In this post
Getting started
"I'm not fat, I'm big boned"
Alpine Linux
When not to use Alpine
Conclusion
Getting started
The assumed starting point of this tutorial is where we left things at
the end of the previous part, corresponding to the part-1 branch of
the repository.
If you prefer, you can also directly checkout part-2, which is the final
result of today's article.
Let's find out with this simple command, to be run from the root of
our project:
The total amounts to roughly 1.5 GB, which is not light. Why is
that?
Most Linux distributions come with many services that are expected
to cover common use cases; they offer a large amount of programs,
intended to address a broad audience whose needs may evolve
over time. On the other hand, Docker containers are supposed to
run a single process, meaning what they need to perform their jobs
usually doesn't amount to much, and is unlikely to change over
time.
Alpine Linux
Alpine is a Linux distribution that takes the opposite approach:
focused on security and with a small footprint, it features the bare
minimum by default and lets you install what you actually need for
your application. The dockerised version of Alpine is as small as 4
MB, and most official Docker images provide a version based on
this distribution.
Before we modify our setup, let's get rid of the current one:
version: '3.8'
# Services
services:
# Nginx Service
nginx:
image: nginx:1.21-alpine
ports:
- 80:80
volumes:
- ./src:/var/www/php
- ./.docker/nginx/conf.d:/etc/nginx/conf.d
- phpmyadmindata:/var/www/phpmyadmin
depends_on:
- php
- phpmyadmin
# PHP Service
php:
build: ./.docker/php
working_dir: /var/www/php
volumes:
- ./src:/var/www/php
depends_on:
mysql:
condition: service_healthy
# MySQL Service
mysql:
image: mysql/mysql-server:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: demo
volumes:
- ./.docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
- mysqldata:/var/lib/mysql
healthcheck:
test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD
interval: 5s
retries: 10
# PhpMyAdmin Service
phpmyadmin:
image: phpmyadmin/phpmyadmin:5-fpm-alpine
environment:
PMA_HOST: mysql
volumes:
- phpmyadmindata:/var/www/html
depends_on:
mysql:
condition: service_healthy
# Volumes
volumes:
mysqldata:
phpmyadmindata:
1 server {
2 listen 80;
3 listen [::]:80;
4 server_name phpmyadmin.test;
5 root /var/www/phpmyadmin;
6 index index.php;
7
8 location ~* \.php$ {
9 fastcgi_pass phpmyadmin:9000;
10 root /var/www/html;
11 include fastcgi_params;
12 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name
13 fastcgi_param SCRIPT_NAME $fastcgi_script_name;
14 }
15 }
You also need to update your local hosts file to add the new
domain name (have a quick look here if you've forgotten how to do
that):
Finally, we also got rid of the mapping of port 8080, since we will
now be using Nginx's port 80 directly.
Next in line is PHP. If you followed the previous part, you already
know that we use a Dockerfile located in .docker/php to
describe and build our image.
1 FROM php:8.1-fpm-alpine
2
3 RUN docker-php-ext-install pdo_mysql
We are now ready to test out our new setup. Run the now familiar
docker compose up -d again, followed by docker compose
images :
The total size of our images now amounts to around 700 MB, which
is less than half the initial weight.
This is why I'm introducing Alpine so early on: instead of going for
the first available image without a second thought, consider your
options and identify what seems to be the best compromise – it will
most likely save you some headaches down the line.
Conclusion
We now have a better idea of how to pick a base image for our
containers, and we optimised our LEMP stack as a result. This is a
good place to upgrade our setup to a more complex three-tier
architecture and to introduce application frameworks, which we will
cover in the next part.
You can subscribe to email alerts below to make sure you don't
miss it, or you can also follow me on Twitter where I will share my
posts as soon as they are published.
25 Comments 1 Login
caused this issue. I need to update the article to reflect this, but in the
meantime you can take a look at this commit and apply the same
changes to your setup. Then do docker-compose down followed by docker-
compose up -d, and it should work.
Thanks for pointing this out – that change was made back in April, it's
probably been broken ever since!
• Reply •
osteel Mod Ernie Pantuso • 2 years ago
1. The aim of part 2 is to use reduced size images, for which Alpine is
great. It also makes sense to use the same HTTP server (in our case,
Nginx) for all HTTP requests, instead of having a second, redundant
HTTP server (Apache) for phpMyAdmin. That being said, there's no
obligation not to if that's easier.
Frankly, I don't use phpMyAdmin myself, but Sequel Ace on macOS. I've
only put it in the series because I know it will be familiar to many.
2. While very similar, MariaDB and MySQL are not the same thing. I'm
trying to stick to a pure LEMP stack in this series as to not confuse
people. This is also why I only use official images whenever possible. I
know a lot of tutorials out there use custom images, but I find that
confusing for newcomers. If you're comfortable using third-party images,
however, by all means do! Basically, what I meant is there is no Alpine
version of the official MySQL image.
• Reply •
$connection = new PDO('mysql:host=mysql;dbname=demo;
charset=utf8', 'root', 'root');
Full explanation
• Reply •
In other words, it looks like you wrote new
PDO('mariadb:host=mariadb... instead of new
PDO('mysql:host=mariadb... in index.php. From what I've
gathered after a quick Google search, the first bit of the
connection string should be mysql, whether the database
engine you use is MySQL or MariaDB.
• Reply •
Jackfusion Jackfusion • 2 years ago
another issue is that phpmyadmin does not load on port
8080 since I exposed 8080:80 in the dokcer-compose file.
• Reply •