Docker -> Building a LAMP stack

Tony Mucci
Code Kings
Published in
5 min readApr 10, 2019

This is a walkthrough on how to build a LAMP stack in Docker. This was a fun research project to see how to create a dev box for my work using Docker and Docker Compose ( Docker’s tool for running an application that requires multiple containers).

Think of docker containers as tiny servers that run only one specific thing. Usually in a server, you would have one instance with a bunch of programs (Apache, PHP, MySQL) installed and running. In Docker, each one of these programs are separated out to their own tiny server that shares resources with the other containers on their host computer/server. In this case, we would have 3 containers

  • Apache
  • PHP
  • MySQL

However for this example, I combined the Apache/PHP programs together. From what I have seen, there isn’t a “best practices” way of docker and you can build things a zillion different ways. So it’s really up to you on how you want to build your containers (tiny servers). Keep in mind that the smaller your container is the better. So if you have some programs that you aren’t sure should be together, follow my little saying:

When in doubt, split them out.

The DockerFiles

DockerFiles are files that you can build a docker image. Think of this file as a script that you would run to set up your environment on a VirtualBox after installing the Host OS (Ubuntu,CentOS, and so forth) and then exporting the appliance for others to use. Docker Images are essentially the same concept. You are creating an image for your tiny server aka container.

DevBox.DockerFile

FROM Command

The FROM command tells the docker file, which images to use as it’s base image. You don’t usually start from complete scratch. I’m sure there are times you can, but they are probably pretty rare circumstances.

In file above, you start with a base image to work from. In this case, we are building off of the latest version of ubuntu.

The syntax for images in docker

repository_name:tag_name

In this example its ubuntu:latest. The latest tag is used in most images to grab the most recent version of the image.

ENV Command

ENV DEBIAN_FRONTEND=noninteractive

The line above is allowing you to set an environment variable within your new images. This would be the same as setting an environment variable while SSH’ed into a server. In this case, this makes it so that when we are installing other software and there is a prompt that requires user input, that it will be bypassed and not impeded the software’s installation. I was having my image build fail on a php extension that needed some input. This allowed me to bypass that.

RUN Command

The RUN commands are as if you are typing in a command in your terminal window. In this file, I was installing the php core and it’s corresponding extensions.

COPY Command

The COPY command copies a file from a local directory on your computer to the container’s file system. Think of it like a scp command on a normal server.

Syntax of Copy Command

/path/to/local/file.txt /path/to/container/filepath/file.txt

CMD Command

The main purpose of a CMD is to provide defaults for an executing container. In this case, we want to launch apache and run it in the foreground so the container stays persistent and active. Unlike a normal server that will run 24/7 until manually powered off, a container will automatically turn itself once it’s finished running. By running Apache in the foreground it keeps the container from powering down.

EXPOSE Command

The Expose command allows whichever port you want to open up INTERNALLY, within the network of the docker containers, but not open to the outside network.

MySQL.DockerFile

Building the image

Now that we have the DockerFiles ready for use, we can build the images into actual container a few different ways. The way I will show you is by utilizing a CLI tool called Docker Compose.

Docker Compose allows you to write a YAML file to spin up multiple containers at once so you aren’t writing a ton of docker commands in your terminal window. You also perform all of this work by writing a bash script with the docker commands, but using Docker Composer makes the script much easier to maintain.

The build command

To run a build using docker-compose (while in the same file directory as your docker-composer.yml file)

docker-compose build

without using any other flags, the docker-compose program will look for the default .yml file name of docker-compose.yml. If you name your .yml a differnt name you would use the -f in the command

docker-compose -f /path/to/docker-compose.yml/file build

The docker-compose.yml

Below is a breakdown of what each line of the YAML file does

More info on Docker Compose File

How to turn on the containers

When you are ready to start your containers (and after you have built the containers), you can run the command ( in the same file directory as your docker-compose.yml file)

docker-composer up

Like the command above when you build your images, you can also specify what your docker-compose.yml filename is by using the -f flag in your command

docker-compose -f /path/to/docker-compose.yml/file build

More info on Docker Compose

How to Connect to a MySQL container with PHP

To connect to a MySQL Db from PHP, you simply use the containers name in your db connection

Example Syntax

mysqli_connect("container_name_here", "my_user", "my_password", "my_db");

So if we were using our MySQL container’s name from above it would look like this: (It’s the name we set in our docker-compose.yml file from earlier)

mysqli_connect("devmysql", "my_user", "my_password", "my_db");

Troubleshooting Tips

Connecting to MySQL issue

Ran into Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0

This was caused by a bind-address line in /etc/mysql/mysql/mysql.conf.d/mysqld.cnf not allowing connections from anywhere for mysql container. I commented it out and restarted the containers and I was able to access MySQL with my Database client (Sequel Pro on Mac)

Final Thoughts

As along as you installed all your web apps dependencies (php-curl, php-json, etc) and made sure your Apache is running, and your MySQL container is running as well; you should be able to visit localhost and see your system running. If you need to, you can always hack your /etc/hosts file to have a domain name point to your localhost (127.0.0.1) Again, only you know what needs to be set in your environment to get your app to work.

All of the things you would run in terminal to get your web app to run, can be placed in your DockerFile, that way it can be performed automatically during your build process.

You use the docker-compose.yml file to trigger booting up all of your containers. Think of it as a script that turns on all of your servers and sets them up to talk to each other.

I hope this simple and quick tutorial will get you a simple LAMP stack box running. From here there are tons more complex builds you can do and even pushing your custom image up to public repos for others to you. Check out Docker Hub to see a list of images that people have posted for you to use.

Happy DevOp-ing!

--

--

Tony Mucci
Code Kings

Co-founder of SimpliCourt, dree, My Company Tools, and Eklect Enterprises