The 06/03/2016

How to use Docker with Magento?

Today we will talk about Docker, obviously applied to Magento but you can adapt this tutorial to any area.

It all started for me there a few months ago, after watching a lecture on testing PHP and specifically tests for continuous integration. I began to wonder how I could incorporate the latest tech Magento to ensure more quality on the e-commerce project teams and how to be more effective? And one morning, I get a message that Thomas said "Hi Peter, I say we set up an offer of accommodation and I will like you to work with us on how it could be integrated with magento properly," okay then I know no more than that but we have to is a time to talk. A few weeks later, I met Jacques was a drink and also tells me about Docker and Vagrant, I said "fuzzy ca Cool would be little that I put myself as" ... From return to Lille, I see Thomas one evening and it shows me Docker .... so I took time to study the solution and test it with magento since this summer. I admit I was a bit lazy, write this article, do the tests etc ... took much time and thought to do more, but when to get out the article here is a first draft. Know that since I finished my tests, I used Docker in my work every day and although I must admit that at first I had a little trouble making it work now that I have I usually find it really handy. I think you will like it. This is quite large and not necessarily easy to read, bear with me I am not a system administrator to the base so sorry if I do not explain everything ultra clear. I urge you to try to create your own containers and make me your feedback, it intéresserai me a lot to know what you thought.

This first article will familiarize you with Docker and understand how the setting up home with magento. This is certainly one of the one I spent the most time on this blog. I'll try to make it simple and to the point, I hope you enjoy it.

What Docker?

First docker is a platform for developers and administrators that allows you to create a "container", a kind of virtual machine that contains application and all its dependencies. You can send this "container" freely to someone who can run it on his machine. Short for simplicity, a docker container is like a virtual machine "light". This is a virtual machine that contains only what is needed to run your application.
We "magento developers," what does that bring us?

Imagine you work on a project and you create a docker container that contains everything you need to work with Magento:
- Apache2
- Php5 and bookshops
- Éventullement more specific to your project libraries ...

You create other containers:
- For rotating ElasticSearch
- For rotating varnish
- One to turn repeat

Thanks to these containers, you have a server architecture with your varnish cache, repeat, search under ElasticSearch and your magento container that works perfectly together.

A new developer should arrive on the project? He loses 1/2 day to install the environment on his machine and if it should change project? with the ports of changes repeat etc ... it's a mess.
With Docker, you transmit your containers, it launches ... it's over! 5min are sufficient.
But that's not all, imagine that instead of transmitting your container to a colleague, you will pass on directly to a host ... finished the problems of "it does not work", it has been tested locally, containers work together. Each work, the host manages memory, storage, security, for its part, is transparent to you, you manage your container ... that's it.

Install Docker and how does it work?

First start by installing Docker on our machine:

sudo apt-get install docker.io

Then we must understand how it works.
A container will be built ( "build") then from that built this object will be called an "image", we will be able to create instances by starting them with the command "run". In our project, we will have a "Mysql" container will be our database server and a container "magento" which will turn our magento (with apache.php). The container "magento" will connect to the container "MySQL" on which he will have his database.

We will start by creating a "Dockerfile" file that will describe our container:
- It will run on Ubuntu
- On top installs Apache 2
- It also installs php5 and extensions required to run Magento (curl, mcrypt, ..)
- Installing the need to connect to a database

. It also creates a container "Mysql" ubuntu that contain "mysql-server", besides we'll start with this one because after magento use it.

Create a container Mysql

The Dockerfile

The DockerFile is the file in which you describe the installation of your machine, install programs, creation of storage volumes, file transfer from your pc, port openings of the machine ..

Start by creating a "mysql" folder with in a "Dockerfile" file that will contain:

from ubuntu 

run apt-get update
run DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade 

run DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server
#run DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-client

run sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf

ADD ./startup.sh /opt/startup.sh

VOLUME ["/var/lib/mysql"]

expose 3306

CMD ["/bin/bash","/opt/startup.sh"]

In this file, I said:
- To be based on an ubuntu distribution
- To update its package
- Install mysql-server and mysql-client
- Replacing the bind-adress 127.0.0.1 0.0.0.0 through in order to connect from outside
- To add the file startup.sh (we will create after) in the / opt / our container
- To have a folder / var / lib / mysql which will be stored on the PC to run my container
- Opening the 3306
- Throw my /opt/startup.sh script (which has added just before) at the end of these treatments

The startup script

Then I create a file that will contain startup.sh:

#/bin/bash
echo "--debut du startup--"
if [ ! -f /var/lib/mysql/libdata1 ]; then
    mysql_install_db

    /usr/bin/mysqld_safe &
    sleep 10s

    echo "GRANT ALL ON *.* TO pfay@'%' IDENTIFIED BY 'pfay123' WITH GRANT OPTION; FLUSH PRIVILEGES" | mysql

    tail -f /var/log/mysql.log
else
/usr/bin/mysqld_safe

fi
echo "--fin du startup--"

This tests if the file / var / lib / mysql / libdata1 exist. This is the storage file of the database.
If it exists, mysql_safe.
We will then launch If there is not, we will create and we will create a user "pfay" with the password "pfay123."
It ends in view the latest entries mysql logs.

Make the Start and Build my container

You have to create the image of my machine to then use it to create the instance.
To simplify things I created a script build.sh but you can pretty much type commands directly. Build.sh The script has the following content:

#!/bin/bash
docker build -t pfay/mysql .

Executed in the folder where is the Dockerfile, the script will take Dockerfile file and create the image "pfay / mysql".
After the build, the image is on your PC, you can start a container from the image.
For this I created a script that run-server.sh to the following content:

#!/bin/sh
docker stop mysql
docker rm mysql
docker run -d -p 3306:3306 -v /data/mysql:/var/lib/mysql --name mysql pfay/mysql

You might as well throw these commands manually but I find it more convenient.

What do this script:
- He stops and removes the "mysql" instance if it exists.
- He then starts with the run command the container he called "mysql" from the image "pfay / mysql" Builde
previously. - It states that the container port 3306 is "plugged" on port 3306 from my machine.
- It also states that the / var / lib / mysql the container will be "connected" with the / data / mysql my machine.
Find the file that party on github: https : //github.com/pierrefay/docker/tree/master/mysql

How to put up with Magento?

Now to Magento container. For this is the same principle (and always will be for your container stevedore) was a Dockerfile file, you make a build to create the image. From the image, an instance is launched.

The Dockerfile file:

from ubuntu
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y php5 php5-cli php5-mysql php5-curl php5-gd php5-mcrypt vim mysql-client
RUN php5enmod mcrypt
RUN a2enmod rewrite
ADD ./000-default.conf /etc/apache2/sites-available/000-default.conf
ADD ./magento /var/www/html
ADD ./config_magento.sh /usr/local/bin/config_magento.sh
ADD ./startup.sh /usr/local/bin/startup.sh
RUN chmod +x /usr/local/bin/startup.sh
expose 80
expose 3306
CMD ["/bin/bash","/usr/local/bin/startup.sh"]

Basically with dockerfile's what we do:
- It is based on an ubuntu distribution.
-
Packets is updated - We install php5 and useful extensions for turning
magento. - Optional: We install mysql-client to test the db command line from the container.
- Optional: It installs vim for editing a file easily when you connect the container.
- On active mcrypt and url rewriting
- The default vhost replaces added by our (we added a few lines to the url rewriting, see the file)
- We added on magento directory (contained in the current folder, how Dockerfile) in the / var / ww / html
our container. - Added the script and config_magento.sh startup.sh
- We modify the rights of the startup script
- We create 2 Volumes / var / www / html / var and / var / www / html / media, we can related to our pc at the launch of the image
- We open port 80 (http) and port 3306 (mysql) of our
VM - We launch the script stratup.sh

Startup.sh the script contains:

#!/bin/bash
echo '----debut du startup'
chown www-data:www-data -R /var/www/html/var /var/www/html/media
chown www-data:www-data -R /var/www/html/app/etc
/usr/sbin/service apache2 start
rm -f /var/www/html/index.html
/usr/local/bin/config_magento.sh
echo '--fin du startup--'
tail -f /var/log/apache2/access.log

This script:
- Set permissions of the file / var / media and / etc
- Start Apache2
- Removes the index.html file defaults to the apache installation
- Starts the script config_magento.sh
- Displays the Apache access logs

. The config_magento.sh file contains the script that installs magento, the variables we defined it to connect to the database and all necessary information to complete the installation of Magento.
The ip of database server is contained in the variable $ MYSQL_PORT_3306_TCP_ADDR which is automatically created at the launch of the container.

#!/bin/bash
clear
CURRENTIP=$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)
SEPARATION="
----------------------------
"
echo "
-----------------------------------------------
----------- CREATION OF LOCAL.XML -----------
-----------------------------------------------"
BDD_HOST=$MYSQL_PORT_3306_TCP_ADDR;
BDD_NAME="magentodemo"
BDD_USER="pfay"
BDD_PASSWORD="pfay123"
SITE_URL=$CURRENTIP
ADMIN_USERNAME="admin"
ADMIN_PASSWORD="admin123"
ADMIN_FIRSTNAME="admin"
ADMIN_LASTNAME="admin"
ADMIN_EMAIL="admin@localhost.fr"
LOCALE="fr_FR"
TIMEZONE="Europe/Paris"
DEFAULT_CURRENCY="EUR"
USE_SECURE="no"
SECURE_BASE_URL=$CURRENTIP
URL_REWRITE="yes"
SKIP_URL_VALIDATION="yes"
USE_SECURE_ADMIN="no"
echo $SEPARATION
echo "DROP DATABASE IF EXISTS $BDD_NAME ;" | mysql -h $BDD_HOST -u pfay -ppfay123
echo "CREATE DATABASE $BDD_NAME" | mysql -h $BDD_HOST -u pfay -ppfay123
echo "Database creation..."
echo $SEPARATION
echo "MySql User and Permissions creation..."
echo "GRANT ALL PRIVILEGES ON $BDD_NAME.* TO '$BDD_USER'@'%' IDENTIFIED BY '$BDD_PASSWORD';" | mysql -h $BDD_HOST -u pfay -ppfay123
echo "OK"
echo $SEPARATION
rm -rf /var/www/html/var/cache
rm -rf /var/www/html/var/session
rm -rf /var/www/html/app/etc/local.xml
echo "Magento Installation..."
php -f /var/www/html/install.php -- \
--license_agreement_accepted "yes" \
--locale $LOCALE \
--timezone $TIMEZONE \
--default_currency $DEFAULT_CURRENCY \
--db_host $BDD_HOST \
--db_name $BDD_NAME \
--db_user $BDD_USER \
--db_pass $BDD_PASSWORD \
--url $SITE_URL \
--use_rewrites $URL_REWRITE \
--skip_url_validation $SKIP_URL_VALIDATION \
--use_secure $USE_SECURE \
--secure_base_url $SECURE_BASE_URL \
--use_secure_admin $USE_SECURE_ADMIN \
--admin_firstname $ADMIN_FIRSTNAME \
--admin_lastname $ADMIN_LASTNAME \
--admin_email $ADMIN_EMAIL \
--admin_username $ADMIN_USERNAME \
--admin_password $ADMIN_PASSWORD
echo "OK"
echo $SEPARATION
echo "Installation Complete !"
echo $SEPARATION

We will then start our container via the run command, I still creates a run-server.sh script:

#!/bin/sh
docker stop magento
docker rm magento
docker run -p 80:80 --link mysql:mysql --name magento pfay/magento

The details of the order you will find above the mysql container. Note the options:
- "-p" That can map port 80 of my container with port 80 my pc.
- "--link" That can link my mysql magento container with the previously launched
container. - "-v" That mounts the volumes previously created in the folder Dockerfile with my pc but will not use here

. That if you start the script run-server.sh your magento container then your vm file is launched and it is connected with your mysql container.
To access it, type the IP of your VM in your browser. To find the IP of a vm, you can use this script getIp.sh:

#!/bin/sh
TAG="magento"
CONTAINER_ID=$(docker ps | grep "$TAG "| awk '{print $1}')
echo "CONTAINER ID : $CONTAINER_ID"
IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' $CONTAINER_ID)
echo "Ip de $TAG: $IP"

As follows :

./getIp.sh magento

Find the file that party on github: https: / /github.com/pierrefay/docker/tree/master/magento

Create your Magento container for teamwork

Ok, you may say, it's great, I have a magento that will work perfectly for a demo but often I'll use it on an existing project, I will not start from scratch and you are right!
You must then create a database on your mysql container, by connecting via mysql-client from your PC, for example, and then import a database.

The Dockerfile will be different because more matter of using config_magento.sh to our development machine, we will rather share the magento directory containing our code in a volume that will ride on our container.
You can find an example of Docker used to develop on github at the following address: https://github.com/pierrefay/docker/tree/master/dev

Of course it must be adapted to your needs.

Connect as SSH on its container dock

You can connect via nsenter on your container, it allows you to connect "as ssh" to eg re-index magento.
Install nsenter:

cd /tmp
curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-
cd util-linux-2.24
./configure --without-ncurses
make nsenter
cp nsenter /usr/local/bin

then you can use this script nsenter.sh:

#!/bin/sh
PID=$(docker inspect --format {{.State.Pid}} $1)
nsenter --target $PID --mount --uts --ipc --net --pid

then you can "fit" into your container by typing:

 ./nsenter.sh nom_du_container
     

And after what can we do?

This tutorial is the first of docker, in the next tutorial we will see how little docker be used to deploy a easily with a specialized server hosting and we will try to answer all the questions you might ask about this article.
Thank you all for reading this article until the end, pending further, feel free to do your own tests and to share your feelings on docker below in the comments on this article, I will be pleased to discuss with you, do not hesitate to ask your questions, depending on your questions I will try to complete this article to be as complete as possible.
You also support this blog by sharing this article on twitter. If you liked this article, follow me on twitter or facebook page of the blog.
Books that can help you :
  • Livre Magento Developer's Guide by Alan Mc Gregor
  • Livre Magento Performance Optimization
  • Livre Grokking Magento Vinai
Comments on this article
No comments yet for this article. Be the first !

You must be logged in to comment an article.