Home | About | Blog | Interesting Reads | Tutorials | Skills | Personal Projects | Books | Fun | Connect with me
Published On: Jul 29 2023
Written By: Krishnan Sethuraman
Category: DevOps
Recently I fixed my old macbook pro and have started using it as my personal computer. Before the mac I used to do most of my programming on an old laptop running LAMP. With the mac joining my arsenal, I wanted the flexibility of using both my mac and the old linux laptop, without going through the struggles of configuring the local environment on my mac. So using Docker was the obvious choice.
So this weekend I decided to containerize my website with docker.
Taking a DB dump
Before starting I took a DB dump of the mysql database from my Linux machine and downloaded it on the mac.
$ mysqldump -u username -p dbname > dbdump.sql
Git branching
I also took a separate branch from the develop branch just to be on the safer side so that if I mess things up I can always ignore this branch and move on.
$ git branch feature/containerizing
$ git checkout feature/containerizing
The file and directory structure of my website looks like the below screenshot. I have not included all the files and directories of the Laravel framework but instead the ones that matter to this article.
So the first step was to create two files Dockerfile and docker-compose.yml
. I usually work on the docker-compose.yml
file first. It gives me a template on what my setup would look like.
Creating docker-compose.yml
For my website I will create an app container for the website, a database container for the blog and newsletter database and phpmyadmin container. I am not a big fan of phpmyadmin and instead love using client tools like DBeaver as I love to write sql queries. However I personally think that including phpmyadmin is a good practice as in projects where you work with multiple developers, phpmyadmin helps in standardising the tools that need to be supported.
In the near future, I will also be implementing caching especially in the blog section and hence decided to include a memcached container for this purpose.
I wanted my the DB data to be persistent and hence included a volume for the DB container.
With all being said my docker-compose.yml looks like this.
version: '3'
services:
app:
build: .
volumes:
- ./laravel-app:/var/www/html
ports:
- 8082:80
environment:
- APP_ENV=local
- APP_DEBUG=true
networks:
- mywebsite
depends_on:
- db
db:
image: mysql:8.0
container_name: mywebsitedb
restart: unless-stopped
environment:
MYSQL_DATABASE: mywebsitedb
MYSQL_ROOT_PASSWORD: password
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- mywebsitedb:/var/lib/mysql
ports:
- 8083:3306
networks:
- mywebsite
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: pma
links:
- db
environment:
PMA_HOST: db
PMA_PORT: 3306
PMA_ARBITRARY: 1
restart: always
ports:
- 8081:80
networks:
- mywebsite
memcached:
container_name: memcached
image: memcached:latest
ports:
- "11211:11211"
networks:
- mywebsite
networks:
mywebsite:
driver: bridge
volumes:
mywebsitedb:
driver: local
I already had mysql installed on both my mac and my linux machine so I decided to use a different post binding for mysql so that I do not have to worry about turning on and off the mysql running on the host.
Creating Dockerfile
With that being sorted I now started working on my Dockerfile so that my containers have the configuration and packages that my project requires.
My Dockerfile looks like this. Most of the steps are pretty straight forward. I am installing a specific version of php and apache along with all associated packages. I also want to run composer install so that I have all my packages installed. In the past I have run composer install on the host machine but I strongly feel this is the best way to do things.
FROM composer:2.4 as build
FROM php:7.4-apache-buster as dev
ENV APP_ENV=dev
ENV APP_DEBUG=true
ENV COMPOSER_ALLOW_SUPERUSER=1
RUN apt-get update && apt-get install -y zip
RUN docker-php-ext-install pdo pdo_mysql
COPY ./laravel-app /var/www/html/
COPY --from=build /usr/bin/composer /usr/bin/composer
RUN composer install --prefer-dist --no-interaction
COPY docker/apache/000-default.conf /etc/apache2/sites-available/000-default.conf
RUN php artisan config:cache && \
php artisan route:cache && \
chmod 777 -R /var/www/html/storage/ && \
chown -R www-data:www-data /var/www/ && \
a2enmod rewrite
As I am running Laravel I need a2enmod rewrite
so I also included a basic apache virtual host config for this purpose. It looks like this and other than the <Directory /var/www/>
section everything else is boilerplate code.
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/public/
<Directory /var/www/>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Firing up the containers
Before firing up the containers I wanted to clear the old containers that I created while testing my configuration.
$ docker system prune -a
The above command is not safe as it wipes out all volume data. I ran it because I was sure that my mac did not have any volume or image I might need. With all old volumes being deleted I fired up my containers. As it's the first, I am also included the build flag.
$ docker-compose up -d –build
After the running I wanted to make sure that all containers were up and running.
$ docker-compose ps
With all containers up and running I made the changes to the env file and opened up the website at http://localhost:8082
.
Restoring the database
With everything up and running the final step is to restore the DB dump file to the database. For this I ran the following command.
$ docker exec -i db-container-name mysql -uroot -ppassword dbname < dbdump.sql
I queried the database to ensure that the restoring the DB dump was a success.
Encountered an issue
During development I experimented with mysql8.0 and mysql5.7. As the volume name was the same this created a complication and the DB container kept restarting. So I had to run the following command to fix it. However, ideally deleting the specific volume would have been suffice.
$ docker system prune -a
Things to note
db
.You can refer to the files in the following Git repo.
P.S. This article assumes that Docker and docker compose is already installed on your computer.