I’ve been using Docker for several months on my development and production environments. With Docker, I’m able to run multiple PHP applications, Django apps and RabbitMQ messaging containers simulteanously without having to deal with software package conflicts. I’d like to share my generic PHP/Apache Dockerfile that can be used to run simple PHP applications.
Docker Basics
According to Docker’s website:
Docker allows you to package an application with all of its dependencies into a standardized unit for software development.
And more:
Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.
In short, it is like running your entire web application in an isolated container as if it is a separate server.
Requirements
Docker needs to run on a Linux environment (you can run it on a VM if you are on Windows or Mac). It is much better if you have a fast connection as well (or run it on a VPS). My sample Dockerfile
is based on Docker 1.6.2.
See the getting started guide on how install docker.
Sample Application
In our example, we are trying to build a simple PHP page, showing phpinfo()
content. Nothing fancy. We will be using CentOS 7 as base image and Supervisord to run our Apache server. Let’s prepare the following files.
Building a Docker image
In order to run a Docker container, we need to create a Docker image first, or use one of the existing images on Docker hub. In our case, let’s build it ourselves.
Let’s organize a bit so we put all our files in one directoty.
mkdir /path/to/docker-build cd /path/to/docker-build
Prepare the files. Based on the list above, we create files like the sample php file, a bash script to start the supervisord application and some apache and supervisord configuration.
File: index.php
Or you could put hello world.
<?php phpinfo();
File: vhost.conf
Our virtual host configuration for Apache.
<VirtualHost *:80> ServerAdmin admin@example.com DocumentRoot /var/www/html ErrorLog /var/log/httpd/default-error.log CustomLog /var/log/httpd/default-access.log combined <Directory "/var/www/html"> AllowOverride all Require all granted </Directory> php_value "date.timezone" "UTC" </VirtualHost>
File: supervisor-httpd.ini
Supervisord configuration to run Apache on start.
[program:httpd] priority = 100 command = /bin/bash -c "/bin/sleep 2 && /usr/sbin/httpd -c \"ErrorLog /dev/stdout\" -DFOREGROUND" redirect_stderr = true stdout_logfile = /var/log/httpd/error_log stdout_events_enabled = true startsecs = 5 autorestart = true
File: start.sh
Entry script where Docker executes upon running the container.
#!/bin/bash __run_supervisor() { echo "Running the run_supervisor function." supervisord -n } # Call all functions __run_supervisor
File: Dockerfile
The most important file is the Dockerifle where it contains instructions on how to build the image. Below is my sample Dockerfile.
It simply instructs the packages to install, copy our prepared files into specific directories, define volumes which make it possible for the files to persist even if we delete the container. Then it defines a port to expose, which is 80
in our example.
Last part defines the entry point where it points to a script that runs supervisord that makes it possible to run Apache on the background.
You can find more information on Docker documentation on how to create a Dockerfile.
FROM centos:centos7 MAINTAINER Leonel Baer <leonel@lysender.com> # Install packages RUN yum -y update && yum clean all RUN yum -y install epel-release && yum clean all # Install MariaDB, Apache, PHP and misc tools RUN yum -y install mariadb-server \ mariadb-devel \ supervisor \ git \ tree \ httpd \ php \ php-bcmath \ php-common \ php-pear \ php-mysql \ php-cli \ php-devel \ php-gd \ php-fpm \ php-pdo \ php-mbstring \ php-mcrypt \ php-soap \ php-xml \ php-xmlrpc \ bind-utils \ pwgen \ psmisc \ net-tools \ hostname \ curl \ curl-devel \ sqlite \ sendmail \ cronie && yum clean all # Add config files and scripts ADD ./vhost.conf /etc/httpd/conf.d/default-vhost.conf ADD ./index.php /var/www/html/index.php # Configure servicies ADD ./start.sh /start.sh ADD ./supervisor-httpd.ini /etc/supervisord.d/httpd.ini RUN chmod 755 /start.sh VOLUME ["/var/www/html", "/var/log/httpd"] EXPOSE 80 CMD ["/bin/bash", "/start.sh"]
Build it
Let’s build the docker image. I prefer to do docker stuff (building image/running containers) using a regular user. You may use root as well.
cd /path/to/docker-build docker build --rm -t generic-php-apache .
The command builds an image. The parameter --rm
tells docker to delete the intermediate containers while running the commands. Since docker commands needs a container for it to run, building an image will create multiple containers that we won’t need, thus we pass the --rm
parameter.
The -t
parameter let you specify the tag name of the image. I used generic-php-apache
in this case. You can specify any custom name.
It should successfuly create an image. Run docker images
to list the available images on your local machine.
Running the container
We can now run our first container. In our example, we will run it at http://127.0.0.1:8080
.
docker run --name=sample-php -d -p 8080:80 generic-php-apache
The command above creates a container called sample-php
, run it on the background via the -d
parameter so that it would continously run, then assign the local port 8080
to map to the containers port 80
. Lastly, we run our container off the generic-php-apache
image.
We should be able to view the page http://127.0.0.1:8080
or if you are using a VPS, it would be like this http://your-vps-ip:8080
.
Explore
To check the currently running docker containers, simply run:
docker ps
Curious what the container looks like? You can login to it. Run this command:
docker exec -it sample-php bash
You should get a shell inside the docker container. You can inspect the files like our sample index.php file or even modify it. It is just like any other server machine although it is abstracted as if it is a real box. To logout of the shell, press CTRL+D
.
You can also stop, start and restart containers. Just remember its name.
docker stop sample-php docker start sample-php docker restart sample-php
You can also create another container using the same image, but runs on different port.
docker run --name=sample-php2 -d -p 8081:80 generic-php-apache
And access it on port 8081
.
Use an existing image from Docker hub
To save you from having the trouble of building the image, you can re-use this existing image. I have pushed this example to the Docker hub.
Docker hub image: https://hub.docker.com/r/lysender/php-apache/
Simply run it like this:
docker run --name=sample-php -d -p 8082:80 lysender/php-apache
You can view the full sample files on Github.
Part 2 coming soon. The database part.
Note: This blog is using the lysender/php-apache
image (the PHP/Apache part).
Enjoy and share.
1 thought on “A sample application running on Docker container – part 1”