A couple of days ago, I noticed that Chris Newell had shared the code for his ergast Formula 1 motor racing results database that I use heavily for my F1DtataJunkie doodles. The code is a PHP application that pulls data from the ergast database, which is regularly shared as a MySQL database dump. So I raised an issue asking if a docker containerised version of the application was available, and Chris replied that there wasn’t, but if I wanted to look at creating one…?
…which I did. After a few false starts, I came up with the solution Chris has since pulled into his ergast-f1-api repo.
The pattern is quite a handy one, and I think reusable – I’ll give it a go for spinning up my own API to look up ONS Geography codes when I get a chance – so what’s involved?
The dockerised application is built from two components launched using docker-compose, a MySQL container and an Apache server configured with PHP5:
ergastdb: container_name: ergastdb build: ergastdb/ environment: MYSQL_ROOT_PASSWORD: f1 MYSQL_DATABASE: ergastdb expose: - "3306" web: build: ./lamp #image: nimmis/apache-php5 ports: - '8000:80' volumes: - ./webroot:/var/www/html - ./php/api:/php/api - ./logs:/var/log/apache2 links: - ergastdb:ergastdb
The server runs the application, makes requests from the linked database container, and returns the result.
As part of my f1datajunkie tinkering, I’d put together a Dockerfle for populating a MySQL database with Chris’ database dump some time ago, so I could reuse that directly.
Which meant all I had to do was get the application up and running… Chris’ original instructions around the API server application were to place the application files into “the root directory” and also add in an Apache .htaccess URL rewrite, which he provided.
Simple… or maybe not..?! Not being an Apache user, it took me a bit of time to actually get things up and running, so here are some of the gotchas that caught me out:
- where’s the “root directory”?
- where should the .htaccess file?
Running a couple of simple tests identified the root directory as the root for the files served by the webserver, and a quick search revealed the .htaccess file should go in the same location.
But the redirects didn’t work…
As a test, I wrote a simple rewrite rule that should have redirected any url to the same test file – but no joy…
A bit more testing suggested I needed to enable the
mod_rewrite plugin, which I did in the appropriate Dockerfile. But still no joy. Because to use patches like the .htaccess file in a server directory also requires allowing “Overrides” to the base Apache settings – which I did (via a crib) by rewriting the Apache config file, again via the Dockerfile that builds the server container image.
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf RUN a2enmod rewrite
Then the database connection didn’t work… But that was easily fixed: I’d forgotten to change the permission is in the appropriate application file.
Now running the docker-compose file with the command
docker-compose up --build -d and it fires up two linked containers. The API is then available via a browser on http://localhost:8000/api/f1 using calls of the form http://localhost:8000/api/f1/2015.json.
So now I have a minimal working example of a PHP application powered by a MySQL database driving a simple web API. Which I can crib from for my own simple APIs…
As to how it could be improved, there are a couple of obvious things:
- the containers are intended for personal, local use: the database is accessed as root and should be properly secured;
- I haven’t got a pattern for updating the database when a new database image is released. The current workaround would be to destroy the containers, and the database volume, then rebuild the images and the containers.
PS to use the local ergast API server from R with my
ergastR package, I needed to tweak the package to allow me to specify the path the API server. I’ll post details of how I did that later…