Whenever we onboard a new developer to ExitShop, the biggest challenge is setting up the system locally, typically on some WAMP (Xampp, Neard…). Usually, it involves three steps:
In the meantime, about a hundred things can go wrong:
Regarding the operating system and services, that is. Of course, you can continue developing in your favorite programs. Docker has been running smoothly under Windows for some time now, so there won’t be any problem in your OS either.
Imagine you have an application running on a specific PHP version, for example, 8. You will want Apache and MariaDB, and the whole thing will run on Debian.
First, install Docker Desktop.
Take the sources from WAMP and copy them somewhere else, for example, to C:\Docker\myapp.
You can turn off WAMP, but keep it in the system. You don’t have to Dockerize every application right away, and these two systems can coexist peacefully.
This is the main file, put it in the root of the application, version it, but don’t upload it to production :)
Here’s an example right away. On the first line, we define which image we want to use. I chose this one, which combines Debian Buster, Apache, and PHP version 8.0.3.
FROM php:8.0.3-apache-buster
COPY docker-config/000-default.conf /etc/apache2/sites-available/000-default.conf
COPY docker-config/my-php.ini /usr/local/etc/php/conf.d/my-php.ini
RUN apt-get update
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
RUN apt-get install -y wget RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb RUN apt install -y ./wkhtmltox_0.12.6-1.buster_amd64.deb
RUN a2enmod rewrite
Next is copying virtual hosts. An example of such a file is below. Note that path. Even though we’re on Windows, we define paths on the chosen OS (Debian).
<VirtualHost *:80> DocumentRoot “/var/www/html” ServerName myapp.test ServerAlias www.myapp.test
<Directory "/var/www/html">
Options Indexes FollowSymLinks MultiViews
AllowOverride all
</Directory>
Next is copying changes compared to the default php.ini file. It could be a higher memory limit, for example.
Then we run an update to have new versions when installing packages. We can install packages as we’re used to on Linux - from repositories or .deb packages. We can cleverly install PHP extensions via docker-php-ext-install XX.
That should be our Dockerfile, defining our container.
This file allows us to combine multiple services into one unit. Put it in the root of the application, version it, but don’t upload it to production :)
version: ‘3.8’
services: web: image: php:8.0.3-apache-buster ports: - ‘80:80’ volumes: - .:/var/www/html/ build: . links: - db extra_hosts: - “myapp.test:127.0.0.1” hostname: myapp.test
db: image: mariadb:10.3.23 restart: ‘always’ ports: - “3306:3306” volumes: - ./docker-config/databases:/docker-entrypoint-initdb.d environment: MYSQL_ROOT_PASSWORD: password
adminer: image: adminer restart: always ports: - 8080:8080
In the example, we see three services. The first is a web server, which we practically configured above. We set the ports it should run on, the hostname, and a volume - where our project should connect in that Debian.
The next service is the database - we choose an image, set the ports, in the volumes section, we can specify the path to the directory (docker-config/databases) where we have the DB structure in SQL files - this will load the DB when we first build the container. And also the root password for the DB.
Note the next service - Adminer. It will run on port 8080, so localhost:8080. Adding more services is that simple.
We have it prepared. We run this command. The images will be downloaded, their installation will be performed, and the commands in our Dockerfile will be executed - installing packages, etc.
docker-compose build
And now we run it all:
docker-compose up
And it should work :)
You can also start containers from the Docker Desktop GUI:
Yes, for larger applications you work on daily, in a team, or that have more specific configuration or service requirements, it is definitely worth it.
But you don’t have to Dockerize everything