• Skip to main content
  • Skip to primary sidebar
  • Skip to footer
  • Home
  • Featured
    • C# Tutorials
      • LinQ Tutorials
      • Facebook C# API Tutorials
    • PHP Tutorials
      • CodeIgniter Tutorials
    • Amazon AWS Tutorials
  • Categories
    • Programming
    • Development
    • Database
    • Web Server
    • Source Control
    • Management
    • Project
  • About
  • Write
  • Contact

CodeSamplez.com

Programming, Web development, Cloud Technologies

You are here: Home / Web Server / How To Dockerize A Multi-Container App From Scratch

How To Dockerize A Multi-Container App From Scratch

February 14, 2015 by Rana Ahsan Leave a Comment

dockerize php application

Recently I had a chance to learn about Docker and also played around with it for a while. It’s amazing technology, which is here to take away all the pain of deployment. In the current world of web hosting services, it’s always a pain to move from one host to another. The major reason is that you will have to configure the new hosting server completely the same way right from scratch manually and if that doesn’t go accurately, things gonna break very badly.

With docker, you have every step documented/defined(in Dockerfile or as a Docker image), and thus it will always be the same, independent of where you are going to host. And most of all, you can automate the creation/configuration of the server, which might take you hours or even days!

Today, I will try to explain how someone can Dockerize an application(which is multi containers based) as a beginner. I will be using PHP and MySQL stack. If you are looking for Dockerizing NodeJS app, then you can follow official example for that. I am using my open-source codeigniterplus PHP/MySQL project as the candidate application.

Backgrounds:

To follow this tutorial, you will need to know how docker works. You can get a rough idea from the official what is docker web page. You can also watch the video, which is very helpful as well. To get your hand dirty, you can try it on interactive web-based terminal to get used to some common commands.

Additionally, here are some terms that we will be using throughout this tutorial, which you will need to know.

  • Docker Image: Docker image is a ready snapshot of a configured server/service. We are free to use a docker image as it is(if sufficient) or extend it to a new docker image to meet our needs.
  • Docker Container: Containers are the running/live in action server/service of Docker images.
  • DockerFile: Dockerfile contains a set of instructions/commands that will be executed to form a new docker image. That Dockerfile can be treated as a well-documented schema version of that docker image.
  • Fig: It’s probably moving forward with a new name called ‘Docker Compose’, recently announced by a recent post on docker blog

Installations:

Basically, you need to have two things set up on your machine where you are trying this tutorial and on the server machine where you are planning to have this docker-based deployment.

  • Docker: Docker has comprehensive instruction pages for several different platforms about installations. Just follow the one you are interested in.
  • Fig: As we will be using fig too, get yourself set up with official instructions.

Step 1: Make Your PHP Project Build-able Completely With Commands:

As we want our solution to be as automated as possible, try to have a set of commands(dependency installation with composer, run PHPUnit tests, change directory/file permissions etc) that will get your application completely ready for deployment. If you have no idea how to do that, you can follow my other tutorial on building php application in single step. You just focus on preparing the application itself, not the environment yet.

Step 2: Create Customize Docker File/Image From An Existing PHP-Based Docker Image:

Now it’s time to get our hands dirty with docker. Basically, you will want a ready image that has PHP installed so that you don’t have to add instructions to install PHP itself on the Dockerfile. If you can’t find anything suitable, you can refer to mine, which I created a few days ago for exercise/testing purposes.

Download PHP/Node Based Docker Image

Now you will have different configuration files for the production environment that you will want to replace or add to the source code. For that, you will have to add instructions manually in the Dockerfile to add them from the host machine to the docker container. In my cases, I have kept those such files in the ‘docker-files’ directory(feel free to store them in a directory you are flexible with).

Here is what my Dockerfile looks like.


FROM ranacseruet/php-node
#App setup
RUN rm -fr /app
RUN rm -fr /app && git clone https://github.com/ranacseruet/dockerized-php.git /app
ADD docker-files/makefile /app/makefile
RUN cd /app && make
ADD docker-files/database.php /app/application/config/database.php
ADD docker-files/run.sh /run.sh
ADD docker-files/.htaccess /app/.htaccess
RUN chmod 755 /*.sh
RUN rm -fr /etc/supervisor/conf.d/supervisord-mysqld.conf
EXPOSE 80
CMD ["/run.sh"]
Code language: HTML, XML (xml)

Just in case you don’t know, the original docker image(from which I created the PHP-node one) uses ‘/app’ as the main root web directory for Apache.

Step 3:(Optional) Create Customize DockerFile/Image For Your MySQL Server:

This step is optional if you want to have some advanced customizations on your MySQL service. I haven’t done anything regarding thus, I didn’t need an additional Dockerfile for this.

In case you are doing this, just remember to have a separate directory for a new Dockerfile.

Step 4: Create Shell Script That will run all initialization commands for you:

If you have some special instructions that you will need to run after the docker image is created, but before you have that service running(such as apache web server), add them in a shell script.

The image I mentioned above has supervisor process monitoring service installed, and applications(apache) run through it, so the only thing I needed is to run the supervisord. I also needed to create a database schema from Doctrine ORM CLI. Thus my shell script looks like below:


cd /app && vendor/bin/doctrine orm:schema-tool:create
exec supervisord -n
Code language: HTML, XML (xml)

Step 5: Create Fig Configuration:

Now it’s time to create a fig configuration file. It includes the configuration for our complete application infrastructure, including how they are connected. So, in this case, it includes two docker container configurations, one for the PHP application itself, and another for the MySQL database. It can also include ports to be exposed(80 for the Apache HTTP server) from a container.

Fig also suppose to facilitate mounting host volume inside containers so that on newer deployment, it can get access to production data on the host machine. But it didn’t work when I tried it on my Mac OSX machine. Most probably because of this open issue for fig on github. Thus I had to follow alternative workarounds. But I will encourage you to try yourself too from the ‘volumes’ section of fig yml official reference guide.

Here is my basic setup in fig.yml:


## YAML Template.
web:
   build: .
   ports:
      - "80:80"
   links:
      - db
db:
   image: mysql
   environment:
      MYSQL_DATABASE: dockerized-test
      MYSQL_ROOT_PASSWORD: root
Code language: PHP (php)

Step 6: Start Up Your Dockerized PHP App!

Well, if you were able to have all the previous steps done properly without any error, now you should be able to run both containers together in one single fig command:


$fig up
Code language: PHP (php)


That’s it! We have our first Dockerized PHP application running with a connection to the database. Congratulations!!

I have kept my test version as a git repository, which you can use as ready-made scripts.

Extending The Setup With More Containers:

As you are a cool developer, I am sure you are not developing only with a database; rather, you might have some more attractive modern services like Redis, Rabbitmq/Gearman message queue, workers etc. Or even more than one PHP application, a mix of PHP/Node/Python/Ruby services etc. You can now go forward with whatever quest you are up to, from this simple two-container setup to as many container setups as you want. Just you should properly mention ‘link’ property to specify which container links to which.

Additional Tips:

tip 1- In production, it’s critical to mount the user data, like uploaded images/files, logs and/or database volumes etc, from the host. You must not save them inside a running container as docker containers are disposable! When there is a new version of your application, you will be creating a new docker image/container with the latest changes, thus losing all previous DB/user data!

tip 2- you don’t have to expose the port externally always, only if you want it to be publicly available. Otherwise, internally linked containers can access each other on any port without any external help. For example, if you haven’t noticed, we haven’t exposed any port for the MySQL database container because we don’t need to. With this feature of docker, you are even more protected now than ever before!

Final Words:

Well, as a disclaimer, I would like to let you know that I am a beginner to Docker myself, and thus my setup shown above to Dockerize an application might not be the most optimized way to get stuff done. As I learn more, I will be able to share better ways in future(so get in touch!). But it should help when you are just starting with a simple setup that you might get excited to see working.

If you are having any trouble/issues with the setups mentioned in this tutorial, please feel free to contact me via commenting below. Happy Dockerizing :)!

Share If Liked

  • Click to share on Facebook (Opens in new window)
  • Click to share on Twitter (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Pinterest (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Tumblr (Opens in new window)
  • Click to share on Pocket (Opens in new window)

You may also like

Filed Under: Web Server Tagged With: deployment, docker, mysql, php

About Rana Ahsan

Rana is a passionate software engineer/Technology Enthusiast.
Github: ranacseruet

Reader Interactions

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 3,774 other subscribers

Follow Us

  • Twitter
  • Facebook

Top Posts & Pages

  • How To Work With JSON In Node.js / JavaScript
    How To Work With JSON In Node.js / JavaScript
  • PHP HTML5 Video Streaming Tutorial
    PHP HTML5 Video Streaming Tutorial
  • How To Work With C# Serial Port Communication
    How To Work With C# Serial Port Communication
  • Facebook C# API Tutorials
    Facebook C# API Tutorials
  • LinQ Query With Like Operator
    LinQ Query With Like Operator
  • Using Supervisord Web Interface And Plugin
    Using Supervisord Web Interface And Plugin
  • Utilizing Config File In C#.NET Application
    Utilizing Config File In C#.NET Application
  • Getting Started With UDP Programming in Java
    Getting Started With UDP Programming in Java
  • Generate HTTP Requests using c#
    Generate HTTP Requests using c#
  • How To Use Hotkeys/Keyboard Events In WPF Application Using C#
    How To Use Hotkeys/Keyboard Events In WPF Application Using C#

Recent Posts

  • Building Auth With JWT – Part 2
  • Building Auth With JWT – Part 1
  • Document Your REST API Like A Pro
  • Understanding Golang Error Handling
  • Web Application Case Studies You Must Read

Tags

.net angularjs apache api audio auth authenticatin aws c# cloud server codeigniter deployment docker doctrine facebook git github golang htaccess html5 http javascript jwt linq mysql nodejs oop performance php phpmyadmin plugin process python regular expression scalability server smarty socket.io tfs tips unit-test utility web application wordpress wpf

Footer

Archives

Follow Us

  • Twitter
  • Facebook

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 3,774 other subscribers

Copyright © 2023