Dockerizing a simple PHP web app

After learning how to download Docker images and run them in containers, I wanted to try my hand at Dockerizing an app myself.

myTinyTodo is a fairly simple PHP web app that uses SQLite for data storage. I have been using myTinyTodo for several years, hosted on a Digital Ocean VPS running on LAMP. My wife and I use it on a regular basis for grocery lists and other shared to-do lists. I knew it should be a good example for Dockerizing an app, and I would then be able to use it myself. It’s also been mentioned a number of times on the /r/selfhosted subreddit, so I know it has other users as well.

This post was helpful in getting started: https://semaphoreci.com/community/tutorials/dockerizing-a-php-application

Preparing the Dockerfile

I followed along the same lines as that tutorial to start by basing my image on the nimmis/apache-php7 image, which would have apache and php installed and configured properly. Ports 80 and 443 were also exposed, and apache was started in the foreground:

FROM nimmis/apache-php7       
MAINTAINER Scott Breakall <scott@breakall.org>
EXPOSE 80
EXPOSE 443
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

Next up, the Dockerfile calls for SQLite to be installed:

 RUN apt update && \       
apt install -y sqlite3 libsqlite3-dev

Now we have apache, php, and sqlite all set up and ready to go.

Next, copy the mytinytodo folder into the apache folder

COPY mytinytodo /var/www/html/html/

myTinyTodo needs write access to the db folder in order to make use of the SQLite database. In addition, clean out the default apache index.html:

RUN chown -R www-data:www-data  /var/www/html/html/db/
RUN rm /var/www/html/html/index.html

GitHub project

Everything described so far is available in this GitHub repo, including myTinyTodo 1.4.3:

https://github.com/breakall/mytinytodo-docker

Building the image

Download the myTinyTodo installation package into the same folder as the Dockerfile, and unzip it to a folder called myTinyTodo.

Execute the following command:

docker build . --tag=mytinytodo 

This will build the image and name is mytinytodo.

user@pc:~/temp/mytinytodo-docker$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytinytodo latest a1c6238be95f 2 hours ago 550MB

Now that the image is built, run the image as a container:

docker run --name mytinytodo -p 80:80 -p 443:443 -d mytinytodo 

Run docker ps to see the container running:

user@pc:~/temp/mytinytodo-docker$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
ca9ce3ab2d0f mytinytodo "/usr/sbin/apache2ct…" 2 hours ago Up 2 hours 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp

Complete setup in the browser

Open the app in the browser to see it running:

I haven’t scripted the database setup since it’s incorporated into the first run of the app anyway, so click the setup.php link.

Click the SQLite radio button, then click Next.

Click Install.

Execute the following to remove the setup.php script:

docker exec mytinytodo rm /var/www/html/html/setup.php 

Reload the main URL:

Success!

Future improvements

SQLite setup

The database setup could be scripted as part of the build process so that the app runs 100% out of the box upon running.

MySQL setup

Since this build is focused on using SQLite, MySQL is not installed at all. If MySQL was desired, the ideal setup would be to have one container to run the PHP app in, and another container to run MySQL in. This could be accomplished by creating two images, and using Docker Compose to orchestrate the creation of two containers that would work together.

Update: the info above is already out of date since I got a couple of buddies to test it out for me, and they had some nice suggestions for improvement in the form of pull requests, which I have merged in (thanks Michael and Max!). But I think the post still holds up to show my process of Dockerizing this simple php app.