*Aug 26, 2024
Introduction
I just clean installed my OS, and was gonna set up my development system and thought: might as well make a blog out of it. We're gonna use docker compose on this guide.
TL;DR: Copy the example here.
Prerequisites
- Docker
- macOS / Windows 11 / Linux
Structure
Folder - docker-compose.yml - Dockerfile - yourfiles ...
docker-compose.yml is a config file allows you to define the services, networks, and volumes required to run your application in a declarative way.
Dockerfile is a text document that contains instructions for building a Docker image.
Example
Here's a working example demonstrating how to use Docker to run a PHP application with Apache as the web server and MySQL for the database.
Note: Some parts are not explained, just google the words and modify it to your needs.
The directory should look similar to this.
Project1 - docker-compose.yml - php81.Dockerfile - index.php - info.php ...
php81.Dockerfile
FROM php:8.1-apache
ENV APACHE_DOCUMENT_ROOT /var/www/html
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
RUN docker-php-ext-install \
mysqli pdo_mysql bcmath exif
RUN curl -sSL https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions -o - | sh -s \
gd zip
RUN a2enmod rewrite
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
It means that use docker image php:8.1-apache, edit apache's document root, move the ini-development file to make the php.ini (when hosting use ini-production), install php extensions, enable mod rewrite, install composer.
You can change php:8.1-apache to php:8.3-apache if you want the latest PHP.
You can change APACHE_DOCUMENT_ROOT to /var/www/html/public if you're using something like Laravel.
You can add php extensions using docker-php-ext-install or using docker-php-extension-installer if the extension needs dependencies not local to the image. Or just only use the latter.
The example above uses the ones that I use and the common extensions, Modify it to your needs. Some extensions are pre-enabled and it depends on the image so please check phpinfo or php -m.
docker-compose.yml
1services:
2 php81:
3 build:
4 context: .
5 dockerfile: php81.Dockerfile
6 extra_hosts:
7 - 'host.docker.internal:host-gateway'
8 ports:
9 - 80:80
10 restart: always
11 volumes:
12 - .:/var/www/html
13 networks:
14 - my_net
15
16 db:
17 image: mysql/mysql-server:8.0
18 command: --default-authentication-plugin=mysql_native_password
19 volumes:
20 - ./mysql:/var/lib/mysql
21 environment:
22 MYSQL_ROOT_HOST: '%'
23 MYSQL_ROOT_PASSWORD: mleopassword
24 ports:
25 - 3306:3306
26 restart: always
27 networks:
28 - my_net
29
30 phpmyadmin:
31 image: phpmyadmin
32 restart: always
33 ports:
34 - 8080:80
35 networks:
36 - my_net
37
38networks:
39 my_net:
40 name: dockernet
It means that make services named php81, db, phpmyadmin that uses the same network. php81 builds using our php81.Dockerfile. db builds using the image mysql/mysql-server:8.0, and so on.
If you are using Windows use backslash (\), and forwardslash (/) when using Linux/Mac. So in Windows it will look something like this C:\project:var/www/html you only need to edit the left side of colon (:), since the right side is the container's.
To Change MYSQL Password, edit MYSQL_ROOT_PASSWORD value.
info.php
<?php
phpinfo();
?>
index.php
<?php
$host = "host.docker.internal";
$user = "root";
$pass = "mleopassword";
$port = 3306;
$conn = new mysqli($host, $user, $pass, "", $port);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "Connected successfully";
$conn->close();
?>
On terminal run the command docker compose up -d in your project directory
You can access the project in your browser using localhost
Check PHP info localhost/info.php
Access phpMyAdmin using localhost:8080
How to Enable Directory Indexing
If you we're using WAMP or XAMPP before, you might have been used on enabled indexing which they defaulted. So, if you want to enable directory listing follow this.
php81.Dockerfile
1FROM php:8.1-apache
2
3ENV APACHE_DOCUMENT_ROOT /var/www/html
4
5RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
6RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
7RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
8
9RUN sed -i 's/Options -Indexes/Options +Indexes/' /etc/apache2/conf-available/docker-php.conf
10
11RUN docker-php-ext-install \
12mysqli pdo_mysql bcmath exif
13
14RUN curl -sSL https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions -o - | sh -s \
15gd zip
16
17RUN a2enmod rewrite
18
19RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
Edit php81.Dockerfile and add this. This line enables directory indexing.
On your terminal run docker compose up -d --build
Go to your browser localhost to see if it reflect changes (should look like image below)
Multiple PHP Versions
So you are wondering how to do set up multiple versions of php using docker? Just add a new service, or (protip: make a Dockerfile per project).
The directory should be similar to this.
Projects - docker-compose.yml - php81.Dockerfile - php56.Dockerfile ...
docker-compose.yml
1services:
2 php81:
3 build:
4 context: .
5 dockerfile: php81.Dockerfile
6 ports:
7 - 8081:80
8 restart: always
9 volumes:
10 - .:/var/www/html
11 networks:
12 - my_net
13
14 php56:
15 build:
16 context: .
17 dockerfile: php56.Dockerfile
18 ports:
19 - 8056:80
20 restart: always
21 volumes:
22 - .:/var/www/html
23 networks:
24 - my_net
25
26 db:
27 image: mysql/mysql-server:8.0
28 command: --default-authentication-plugin=mysql_native_password
29 volumes:
30 - ./mysql:/var/lib/mysql
31 environment:
32 MYSQL_ROOT_HOST: '%'
33 MYSQL_ROOT_PASSWORD: mleopassword
34 ports:
35 - 3316:3306
36 restart: always
37 networks:
38 - my_net
39
40 phpmyadmin:
41 image: phpmyadmin
42 restart: always
43 ports:
44 - 8082:80
45 networks:
46 - my_net
47
48networks:
49 my_net:
50 name: dockernet
php56.Dockerfile
1FROM php:5.6-apache
2
3ENV APACHE_DOCUMENT_ROOT /var/www/html
4
5RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
6RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
7RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
8
9RUN sed -i 's/Options -Indexes/Options +Indexes/' /etc/apache2/conf-available/docker-php.conf
Run the command docker compose up -d
PHP 8.1 localhost:8081
PHP 5.6 localhost:8056
Final Thoughts
Remember to check ports if you are using many containers. Play with it and learn. GLHF.