Are you still using XAMPP or another local web server in 2021? Read on and find out why you should stop doing so right now. There’s a much better way to set up your environments. This is the way forward.
In this article, we’ll introduce Docker and show how to set up Docker for PHP. While our example shows a PHP server, this method applies to most if not all servers, such as NodeJS, Java, C#, and others.
What’s wrong with my local web server?
Sure, XAMPP or any other local web server by itself is a useful toolbox, allowing you to run a PHP server easily on your machines. There are multiple issues though, let’s take a look at them below.
- A local web server needs to be installed on every machine
That’s right, you’ll have to manually install your local web server on every single machine, while every machine should have the same configuration.
- A local web server only supports one web server configuration
If you need more configurations you’ll have to install and run multiple local web server configurations and instances. Considering this is a manual setup, this is no fun.
- The local server setup is not saved in your codebase
That’s right, if you lose your configuration, you’ll have to make it from scratch again.
- Manual Database setups
Are you installing your PHP application to another server? You’ll have to also re-do the entire database setup and preparation. There’s a better way.
- Manual Upgrades
Upgrading the PHP version in a local web server is a manual effort. Can this not be faster?
- With a local server, new developers need to ask for the setup or read from documentation
Shouldn’t there be a one-click way to set up an environment locally, saving time for everybody?
There is a solution to all of these problems. That is Docker containers.
If you are working on small prototypes and none of these issues seem recognizable, you will mostly be fine working on a local server setup. If not, read on and discover how we can solve these problems together and move forward.
What is Docker? What does it do?
Docker allows you to run your applications in a consistent manner. Configure once, run any time, and anywhere. Developers write simple configuration files, which instruct Docker on how exactly to startup your application. Behind the scenes, Docker spins up virtual containers, which are lightweight software images that can be run independently on your machine.
These configuration files are committed to the code repository. New developers simply clone the repository and run Docker. Et voilà, the server is started up with all the necessary dependencies automatically.
Do you remember having to run composer install, set up a database locally, populate the tables, set up the configuration files, and so on? That’s all part of the past.
Instead, we can write a script in Docker that will, first of all, install the composer dependencies required, run a MySQL server, automatically insert the database data from a pre-existing SQL file and finally run your PHP server. This is all done in one simple click. New developers do not even need to know how it is being run, it just works. We will go over this in the next sections of this article.
By itself, Docker containers emerged in 2013, but in practice, there are a lot of developers who do not know how to work with them yet. Let’s change this around in 2021 and hail to proper application setups! While Docker configurations can take up some time, it is in many cases worth it in the long run. It is also very fun to set up the Docker configurations. It is delightful to see how easy they are to run, and how much time you’ll save in the future. Efficiency is king in the tech world.
First of all, we need to understand the concept of images. Docker works with images of software, which are similar to virtual machine images, but instead of containing a full operating system (which takes space and makes it the opposite of lightweight), the images only contain the software.
Docker Hub contains a lot of free to use images, such as php servers and so on. If we were to search for php, we would find a lot of different php images to use, such as php-8-alpine (which is a lightweight version of PHP 8) and so on.
All of these images can be used in your configuration. Setup a php-8 and mysql server? Use both images in your configuration. Want to test your application with php-7? Simply switch the php version in your configuration file, it really is that easy.
Now that you understand why we need Docker, what it does and how it works, let’s jump right into the code!
Types of Docker Configuration Files
Docker typically has three configuration files. Let’s go over how these work.
This file instructs Docker, which services need to be run, and how. For example, if we need a PHP and MySQL server, we’ll need to define a service called php and another service called mysql.
We can then configure some of the run options. Should the service restart if it went down? Which port should it run on? What is the root folder for the PHP server?
The Dockerfile enables you to create your own Docker software images. For instance, the default php-8-alpine does not include PDO, MySQL, or ZipArchive classes. In order to add this functionality to the php image, we’ll need to create our own docker image.
This file allows you to define which local files should not be copied over to your Docker image. It helps you make the builds more lightweight and fast.
These three files: docker-compose.yml, Dockerfile, and .dockerignore are vital for your Docker setup. Make sure to commit and safely store these inside your code repository.
In the next section, we’ll take a look at setting up Docker purely with the docker-compose.yml configuration file. In our next article, we’ll take a deep dive into creating a custom Docker image for more customization options.
Setting up a simple php server in Docker
Before we continue, please make sure to download and install Docker Desktop onto your machine.
Let’s create a new project, in a new folder. Let’s call it, simple-php. Let’s create a sample index.php file.mkdir simple-php && cd simple-php
Add the following index.php file contents<?php echo "Hello Docker!";
Now, we’ll want to run this on a PHP 8 server. Let’s find an appropriate image on Docker Hub. By searching for php, we can find the php Docker image. This image has multiple tags, such as 8-alpine, which indicates version 8, as well as the lightweight alpine version. This is exactly what we need. The tag can be added after the image name, with a colon.php:8-alpine
Let’s set up a docker-compose.yml file and use the php:8-alpine image.# Create the docker-compose.yml file
touch docker-compose.yml# Let's enter the contents for the docker-compose file below:# First, indicate the version of Docker compose we want to use
version: '3'# Create a section for all the services/images we need
# Create a PHP service, call it however you'd like
# Optionally, choose a container name
container_name: "php" # Select the Docker image to use for this service
# Set up to automatically restart in case the container goes down
restart: always # Map your local PC port to the container's port, so you can get access to the container this way
# Format local:docker
- 8080:8080 # The command to be run, this command sets up a local PHP development server on port 8080
command: php -S 0.0.0.0:8080 # Select which files should be copied over to the PHP server
- .:/var/www # Set up hostname and file locations inside the image
Now, let’s run the server by letting Docker do its magic!$ docker-compose upCreating network "app_default" with the default driver
Pulling php (php:8-alpine)...
8-alpine: Pulling from library/php
596ba82af5aa: Pull complete
af74f285bb27: Pull complete
2ab8440e5667: Pull complete
64889fa545ec: Pull complete
94168e648735: Pull complete
3898f14298ef: Pull complete
c3747e5f2167: Pull complete
7c3df0f80888: Pull complete
e1f6ddeaf0bd: Pull complete
Status: Downloaded newer image for php:8-alpine
Creating php ... done
Attaching to php
php | PHP 8.0.1 Development Server (http://0.0.0.0:8080) started
If you then browse to http://localhost:8080/ you should be able to find your Docker service running.
It is very nice that the PHP server will function as any regular PHP server would. If you change any files within your project’s directory (as defined in the volumes section of your docker-compose.yml), the changes will be automatically reflected. This is because Docker uses a sort of symlink towards the folder defined in the volume.
You can also choose to run your docker service in the background, by adding the -d argument.$ docker-compose up -d
Creating network "app_default" with the default driver
Creating php ... done
If you then wish to turn it off, you can run the following command.$ docker-compose down
Stopping php ... done
Removing php ... done
Removing network app_default
Now, try installing it onto another machine. Simply clone your repository, and run$ docker-compose up
And voilà, your application is fully running, with a completely portable setup that does not require any local server to be present. How neat is that?
Note, in this example, we are making it simple by using the local web server functionality of PHP (instead of having to configure apache/nginx). This is fine for a development server, and it saves us some configuration. However, if you’d like to have your container deployed to a production environment using the same docker configuration, make sure to set this up with apache or another web server. Feel free to give it a try to set it up together with apache. We’ll cover this in one of our next articles as well.
Now that you understand how to set up a simple server using Docker, try adding a second service for a MySQL server. Go to Docker Hub, find the appropriate images and configurations, and set it up.
In our next article, we will guide you through the process of adding the MySQL setup to our current configuration, as well as automatically adding data to the MySQL server and automatically running composer install.
We have seen Docker containers can have quite some advantages
- Portable setup, environment backed up in a configuration file
- One-command to get the entire application up and running (!)
- Does not require any local configurations, except installing Docker
- New developers can immediately start work and don’t have to spend too much time setting up the environments locally
- Sturdy set up. With a local server, it can always break due to configurations or other. With a container, you could simply restart Docker.
There are more advantages, some of which we haven’t seen yet. For example,
- The docker image running locally can be deployed, guaranteeing the deployed environment will behave in the same way as your local environment.
- The same applies to sharing a specific version of the software image with your fellow developers, they should be able to reproduce just the same behavior.
We have also seen how Docker uses three important configuration files.
- docker-compose.yml (which we have used to set up a php server together)
- Dockerfile (which will be used for a set up in our next article)
- .dockerignore (which will also be used in our next article)
Finally, we set up a php server for local Docker container development together.
Don’t forget, try to set up MySQL as an extra service and we will meet again in our next article, showing you exactly how you can do this, while also having some extras such as automatically populating SQL data.
While Docker already exists since 2013, it is a very solid option for configuring environments in 2021, be it for local development, or production deployments.
Some alternatives exist, such as Kubernetes which we will discuss once our Docker article series is complete.
Let us know in the comments, what do you think of Docker? Was the setup easy? How easy is it to run your php server now? We’re very curious to know, please show us your creations!