This collection of Docker Compose (actually only one) will help you to host several websites locally, each with individual *.localhost
subdomain and specific Apache/PHP version and settings:
The reverse proxy:
The demo stack:
- https://hub.docker.com/_/httpd
- https://hub.docker.com/_/php
- https://github.com/mlocati/docker-php-extension-installer
- https://hub.docker.com/_/mariadb
- https://www.adminer.org/
The WGUI management interface:
https://docs.docker.com/engine/install/
git clone https://github.com/Germain-Italic/docker.git
cd docker
docker-compose -f nginx-proxy/docker-compose.yml up --build --detach
Default: you should see a 503 error on http://localhost/
LAMP-Alp-2.4-10.4-7.4 is composed of:
- Linux Alpine (latest)
- Apache 2.4 (latest)
- MySQL using MariaDB 10.4
- PHP 7.4
First, rename docker/LAMP-Alp-2.4-10.4-7.4/.env.dist
to .env
, then build and launch:
mv docker/LAMP-Alp-2.4-10.4-7.4/.env.dist docker/LAMP-Alp-2.4-10.4-7.4/.env
docker-compose -f LAMP-Alp-2.4-10.4-7.4/docker-compose.yml up --build
Use ctrl+C
to exit the process. Add --detach
to have your shell back.
Mac / Linux
# sudo nano /etc/hosts
# replce
127.0.0.1 localhost
# by
127.0.0.1 localhost *.localhost
Windows
Use Hostsman
- You should see a directory listing at http://lamp-alp-2.4-10.4-7.4.localhost/
- You should see a technical page at http://lamp-alp-2.4-10.4-7.4.localhost/docker-infos/ which looks like this:
Duplicate and rename the demo project, change the variables, launch the new stack:
NEWPROJECT=myproject
echo $NEWPROJECT
cp -r LAMP-Alp-2.4-10.4-7.4/ ${NEWPROJECT}
sed -i "s/lamp-alp-2.4-10.4-7.4/${NEWPROJECT}/g" $NEWPROJECT/.env
docker-compose -f ${NEWPROJECT}/docker-compose.yml --env-file ${NEWPROJECT}/.env up --build --detach
If you are adding this project for the first time, add the external ${NEWPROJECT}_public
newtork to nginx-proxy/docker-compose.yml
nginx-proxy/docker-compose.yml
!
printf '%s\n' '0?external: true?a' " ${NEWPROJECT}_public:"$'\n external: true' . x | ex nginx-proxy/docker-compose.yml
printf '%s\n' '$+?ports:?i' ' - '${NEWPROJECT}'_public' . x | ex nginx-proxy/docker-compose.yml
Rebuild and launch the proxy with the extra network:
docker-compose -f nginx-proxy/docker-compose.yml --env-file nginx-proxy/.env up --build --detach
If you just want to stop/delete the ${NEWPROJECT}
stack's containers without deleting the project files from your drive, skip this step.
If you wan to delete the project completely, you will have to tear down the reverse proxy first because it has a link to the ${NEWPROJECT}_public
external network.
If you remove the ${NEWPROJECT}
containers without stopping the reverse proxy, however the ${NEWPROJECT}_public
network won't be deleted.
To delete volumes, type down -v
instead.
NEWPROJECT=myproject
docker-compose -f nginx-proxy/docker-compose.yml --env-file nginx-proxy/.env down
docker-compose -f ${NEWPROJECT}/docker-compose.yml --env-file ${NEWPROJECT}/.env down
docker-compose -f nginx-proxy/docker-compose.yml --env-file nginx-proxy/.env up --build --detach
cd myproject
# keep the console open and show the logs
docker-compose up
# or
# hide the logs
docker-compose up -d
# rebuild containter
docker-compose up -d --build
# restart all services in container
docker-compose restart
# restart a single service
docker-compose restart db
# _Stops containers and removes containers, networks, volumes, and images created by up_
# from https://docs.docker.com/compose/reference/down/
docker-compose down
docker-compose down -v # Warning, will delete data
# stop a single service
docker-compose down apache
db
container instance with a data directory that already contains a database, the $MYSQL_ROOT_PASSWORD variable will in any case be ignored, and the pre-existing database will not be changed in any way.
# load environment variables into current shell
# so you don't have to memorize PROJECT variable (default project is lamp-alp-2.4-10.4-7.4)
source .env
docker exec -it ${PROJECT}-apache /bin/ash
docker exec -it ${PROJECT}-php /bin/ash
docker exec -it ${PROJECT}-db /bin/bash
Get the random port assigned to mysql image, in this case, internal mysql port 3306 is mapped to external port 49237 on ipv4 and ipv6
# full output
docker port ${PROJECT}-db
3306/tcp -> 0.0.0.0:49237
3306/tcp -> :::49237
# or, just the port
docker port ${PROJECT}-db | rev | cut -d ":" -f1 | rev | tac | sort -u -t: -k1,1
49237
Then:
mysql --port=49237 --protocol=tcp -u root -p${MYSQL_ROOT_PASSWORD}
OR, with a cool one-liner:
mysql --port=`docker port ${PROJECT}-db | rev | cut -d ":" -f1 | rev | tac | sort -u -t: -k1,1` --protocol=tcp -u root -p${MYSQL_ROOT_PASSWORD}
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 5.5.5-10.4.18-MariaDB-1:10.4.18+maria~focal mariadb.org binary distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
docker exec -it ${PROJECT}-db /bin/bash -c "mysql -u root -p${MYSQL_ROOT_PASSWORD}"
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 15
Server version: 10.4.18-MariaDB-1:10.4.18+maria~focal mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
Show containers logs
If you run with docker-compose up -d
logs don't show up. Use the followings:
docker logs ${PROJECT}-apache
docker logs ${PROJECT}-php
docker logs ${PROJECT}-db
Portainer is a lightweight management UI which allows you to easily manage your different Docker environments
docker-compose -f portainer/docker-compose.yml up --detach
Then go to http://localhost:9000/ and chose the Docker stack on setup.
It is simply a wrapper to the default installation command (from the docs):
docker volume create portainer_data
docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
http://localhost:9000/#!/1/docker/containers
- https://dockstation.io/ (GUI, cross platform)
- https://github.com/jesseduffield/lazydocker (TUI, cross platform)
Obtain the upstream default configuration from the container:
docker run --rm httpd:2.4 cat /usr/local/apache2/conf/httpd.conf > conf/httpd/httpd.conf.dist
- Rename httpd.conf.dist to httpd.conf if you want to reset your configuration to Apache's default.
- Edit httpd.conf.dist to suite your needs, exemple: try disabling directory listing.
Default:
Edit the line Options +Indexes
in httpd.conf
(switch +
with -
).
Restart the container:
germain@xps:~/Sites/docker/LAMP-Alp-2.4-10.4-7.4$ docker-compose restart apache
Restarting lamp-alp-2.4-10.4-7.4-apache ... done
After:
Obtain the upstream default configuration from the container:
docker run --rm php:7.4-fpm cat /usr/local/etc/php/php.ini-production > conf/php/php.ini-production.dist
docker run --rm php:7.4-fpm cat /usr/local/etc/php/php.ini-development > conf/php/php.ini-development.dist
Rename php.ini.orig to php.ini if you want to reset your configuration to PHP's default.
It is strongly recommended to use the production config for images used in production environments!
You may want to tweak (default values):
upload_max_filesize = M
post_max_size = 8M
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
;date.timezone =
Edit /LAMP-Alp-2.4-10.4-7.4/conf/php/Dockerfile
to suite your needs.
For example, add mysqli
to pass all tests on http://lamp-alp-2.4-10.4-7.4.localhost/docker-infos/
Before:
# docker/LAMP-Alp-2.4-10.4-7.4/conf/php/Dockerfile
FROM php:7.4-fpm-alpine
RUN docker-php-ext-install \
pdo_mysql \
mysqli
Rebuild container
docker-compose up --build --detach php
After:
- Adminer: always pull latest version
- Default page (http://localhost): create a welcome page that lists all available vhosts
- Test https w/ Let's Encrypt
- Create a virtualhost generator from template
- Enforce restricted visibility of DOCKER_ALIAS to external networks inside Apache configuration
- Avoid duplicate network names on project duplication
- https://blog.gougousis.net/file-permissions-the-painful-side-of-docker/
- https://vsupalov.com/docker-shared-permissions/
- https://medium.com/redbubble/running-a-docker-container-as-a-non-root-user-7d2e00f8ee15#:~:text=The%20Problem%3A%20Docker%20writes%20files,owned%20by%20the%20root%20user
- https://forums.docker.com/t/systemd-coredump-taking-ownership-of-tmp-db-directory-and-contents-in-rails-app/93609