Getting started with Docker
Tags: posts, devops, docker, php
Published: 2019-06-07 09:35:31

---
title: Getting started with Docker
published: true
tags: Posts,DevOps,docker,php
canonical_url: http://blog.adnansiddiqi.me/getting-started-with-docker/
---

## Introduction

In this post, you are going to learn what Docker is and how it can help you not only to keep your developing environment organized but also portable to any machine irrespective of the operating system. This is the first part of the series. Read on!

## What is Docker?

> Docker is a computer program that performs operating-system-level virtualization, also known as “containerization”.[6] It was first released in 2013 and is developed by Docker, Inc.[7]
> 
> <cite>Wikipedia<br></cite>

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/virtualbox-1024x795.png)

## History

Docker is not the first such attempt. Earlier we saw attempts like VMWare and Oracle’s VirtualBox were made. I remember when I was working for a company in 2007, I had to manage different copies of **VMWare** containing **IBM Websphere** and **FileNet** that was minimum in 60GM in size. You also needed a machine with a good resource ( ~ 4GB of RAM at that time) to run it smoothly. It was very tedious, nevertheless, because you were importing an entire operating system and it’s resources in your _host machine_ (_the machine that runs VMWare itself)_. After a few years, [Vagrant](https://en.wikipedia.org/wiki/Vagrant_(software)) came into the market. Vagrant improved the portability and flexibility in a way that it provided a wrapper around existing VirtualBox, called Vagrant Box and let the developers log into it via terminal instead of going via GUI route. Still, it was not helping much in portability. It did solve the problem of isolating the development environment though but at the cost of using too many resources. Things were working like that and then the Docker was born.

Docker solved a few main problems:

- Implementing virtualization with the help of Linux Containers which made it very lightweight and less resource hungry.
- Providing a mechanism of deploying entire containers as it is on remote machine thus killed the infamous developers’ excuse: _But it works on my machine!_ by letting deploy the entire system(DB connections, servers, libs etc as it as they were working on a developers machine).
- Since containers are isolated environments, it then allows developers to use the latest versions of existing software and even the software that are not compatible with their own host operating system. For instance, a developer on his Windows machine can run servers inside a Docker container that are only available for Windows. 
- Mimic a scaleable scenario on a developer by running multiple containers for a server.
- Implement and test a [micro-services architecture](https://en.wikipedia.org/wiki/Microservices) on a single machine without getting worried about resources.
- Creating a Workflow for a seamless deployment.

And probably many more!

## Docker Architecture and its working

The entire docker environment is based on client-server architecture. The docker client, which runs on your machine, interacts with docker daemon, called, `dockerd` and performs operations. It is not necessary that both docker client and daemon reside on the same machine. The docker client could interact with a remote daemon as well. The image depicts the entire system flow.

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/DockerArch2.jpg)

#### Images

An image is a template that consists of instructions on how a container should be created. Think of it a recipe that consists of instructions that how to use ingredients to make a dish. Every image is based on a _base_ image which usually belongs to an operating system. For instance, you download a Java image which itself could be based on a <g id="14" data-gr-id="14">base </g>`ubuntu`<g id="14" data-gr-id="14"> image</g>. You can create your own image by creating a file, called, `Dockerfile` that contains a set of instructions to make an image. Suppose you are a technical lead in your company and response to provide a development environment for juniors or each new hiring. The ancient and traditional way is that you ask network guy or the new employ to install certain <g id="11" data-gr-id="11">softwares</g> on your machine like Git, AWS client etc on his machine. The process could be slow as you’d have to visit each person and configure his client tools for remote servers. The _docker wa_y is that you create a `Dockerfile` and put everything the developer should have for a kickstart. What all is required for him to build an image and make everything up and running in a few mins.

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/containers.jpeg)<figcaption>Shipping Containers<br><br></figcaption>

#### Containers

A container is the running instance of the image. Think of it as a dish prepared with the help of a recipe. So whatever you put in your `Dockerfile`, you see the output of it in your container. The idea of a container was taken from shipping containers which contain different goods and are move as it as from one place to other. An app within a docker container follow the similar approach and make a developer’s life easier.

#### Registry

Docker registries are actually repositories which store images. You can have a public registry like [Docker Hub](https://hub.docker.com) or private registry pertaining images related to your organization. When you execute docker commands like `run`, `pull` <g id="161" data-gr-id="161">or </g>`build`<g id="161" data-gr-id="161"> it</g> actually downloads the image from the remote registry.

## Installation

Docker is available for Windows, Linux, and Mac which you can download from [here](https://www.docker.com/get-started). I am on Mac so have no choice other than using the OSX version for this tutorial but I am pretty much sure it is akin to the [Windows](https://docs.docker.com/docker-for-windows/install/#start-docker-for-windows) one. Once installed, go to the terminal or Shell and run the following command:

`docker version`

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/docker_version_command-1024x544.png)

You will see a different version as you can see mine one is pretty old and can’t upgrade due to my OSX limitations. Regardless of that, if you can see something similar it means all is well. Shall we move on? Good! read on.

The object is to setup a development environment related to PHP and MySQL so that you can create php based web apps. You are willing to use the latest version of PHP and MySQL. For this tutorial I will go for PHP 7.3.x and MySQL8. You want to keep your code on Github so for that you must have **Git** installed.

## Creating <g id="20" data-gr-id="20">Dockerfile</g> file

I already brief above what <g id="14" data-gr-id="14">is </g>`Dockerfile`<g id="14" data-gr-id="14"> all</g> about so it’s time to start creating our own. Before you do that, create a folder with name `DockerPHPTutorial` and inside that create a subfolder with <g id="16" data-gr-id="16"><g id="13" data-gr-id="13">name</g> </g>`src`<g id="16" data-gr-id="16"> which</g> will keep all the source code related to your app. Make sure <g id="28" data-gr-id="28">that </g>`Dockerfile`<g id="28" data-gr-id="28"> is</g> in the root folder. Folder structure will be something similar to the given below:   
**.**  
├── Dockerfile  
└── **src**  
    └── index.php

Now it’s time to start finding our required PHP image. For that, I will head to _Docker Hub_ website and search PHP. I will go with the [Official Image](https://hub.docker.com/_/php).

If you scroll down a bit you will find a heading **Supported tags and respective Dockerfile links** where you can find your required image. I will go with **7.3-apache (Ctrl+F for search)** because besides PHP I need to have Apache web server installed as well. After all, I have to run websites! If you click on the [link](https://github.com/docker-library/php/blob/a280ab8e8790052338ce59a1fee739df8f831f16/7.3/stretch/apache/Dockerfile) of it, you will find it another `Dockerfile`. I discussed above that images could be developed with a base image. If you visit the Dockerfile of it you will find that the image itself was developed from _Debian Stretch_, how did I find it? <g id="48" data-gr-id="48">well</g> I found the <g id="52" data-gr-id="52">line </g>`FROM debian:stretch-slim`<g id="52" data-gr-id="52"> which</g> tells that the **7.3-<g id="10" data-gr-id="10">apache</g>** image is based on Debian Stretch. If you read further down you will find commands to install PHP and Apache and how to make it run.

So, the first line <g id="6" data-gr-id="6">of </g>`Dockerfile`<g id="6" data-gr-id="6"> </g><g id="7" data-gr-id="7"><g id="6" data-gr-id="6">is</g> </g>`FROM php:7.3-apache`<g id="7" data-gr-id="7"> which</g> eventually <g id="8" data-gr-id="8">calls </g>`docker pull`<g id="8" data-gr-id="8"> command</g>. If you just mention `docker pull php `it then pulls the image having <g id="9" data-gr-id="9"><g id="5" data-gr-id="5">tag</g> </g>`:latest`<g id="9" data-gr-id="9">.</g> Learn more about it on [this](https://docs.docker.com/engine/reference/commandline/pull/) link.

```
FROM php:7.3-apache COPY src/ /var/www/html/ EXPOSE 80
```

The second line is used to copy data from <g id="9" data-gr-id="9">host</g> machine’s `src`folder. <g id="12" data-gr-id="12">Why </g>`/var/www/html`<g id="12" data-gr-id="12">?</g> The answer you will find in the Dockerfile of the PHP image where the document root is being set. The next <g id="11" data-gr-id="11">is </g>`EXPOSE`<g id="11" data-gr-id="11"> which</g> is kind of documenting what port do you want to expose. If you <g id="8" data-gr-id="8">don’r</g> mention the port then the container will listen to all ports. All is set, it’s time to run build it:

```
docker build -t php\_img .
```

right <g id="10" data-gr-id="10">after </g>`docker build`<g id="10" data-gr-id="10"> you</g> use <g id="11" data-gr-id="11">the </g>`-t`<g id="11" data-gr-id="11"> switch</g> to set the tag of your image, in this <g id="7" data-gr-id="7">case</g> it is set to _php\_img_. After that you mention the path of <g id="13" data-gr-id="13">the </g>`Dockerfile`<g id="13" data-gr-id="13">,</g> in this <g id="8" data-gr-id="8">case</g> it is in the current directory hence <g id="12" data-gr-id="12">mentioned </g>`.`<g id="12" data-gr-id="12"> only</g>. To learn other options available visit the reference [here](https://docs.docker.com/engine/reference/commandline/build/).

Alright, once build, you can verify it by running the command `docker images` in the terminal.

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/docker_images_command-1024x82.png)

Notice the column _REPOSITORY_ and **TAG** , you can see **php\_img** under _REPOSITORY_ section and _latest_ under **TAG** section. Docker recommends you to set name in **name:tag** format. So when you run the build command like `docker build -t tut:php_img . ` then it will then show like below:

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/docker_images_command1-1024x72.png)

Now **tut** is under _REPOSITORY_ and php\_img under TAG section. When you don’t mention under Repo<g id="5" data-gr-id="5">:tag</g> format then it uses the main image tag. In this case **latest** of _PHP_ image.

It’s build but not running. This is similar to compile a program. When you build, it’s just create a binary but not executing it. You gotta run it. Same is here. You only have BUILT an image, You still have to run it, for this you have to run `docker run`command.

```
docker run -p 80:80 tut:php\_img
```

And when I run it, I get this!

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/apache_error.png)

Ouch! what happened! Looks like file permission issue. Turns out that the image volume is not mapped with our host machine path. If you are on OSX and probably windows too, Docker is allowed to mount a few selective folders only. Click on Docker Icon, go to preference \> File Sharing and add the absolute path of the folder where your app files will reside:

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/docker_pref.png)

You also have to make changes in your `docker run` command:

`docker run -p 8000:80 -v /Development/PetProjects/DockerPHPTutorial/src:/var/www/html/  tut:php_img`

So first the volume was mounted and then <g id="8" data-gr-id="8">used </g>`-v`<g id="8" data-gr-id="8"> <g id="5" data-gr-id="5">switch</g></g> to map local folder with docker image folder. <g id="7" data-gr-id="7">Oh</g> and before you head to <g id="6" data-gr-id="6">browser</g>, don’t forget to create a <g id="9" data-gr-id="9">file </g>`index.php`<g id="9" data-gr-id="9"> </g><g id="10" data-gr-id="10"><g id="9" data-gr-id="9">under</g> </g>`src/`<g id="10" data-gr-id="10"> folder</g>. I just <g id="19" data-gr-id="19">put </g>`phpinfo()`<g id="19" data-gr-id="19"> in</g> it. If all goes well, the following screen should be enough to pat your own back.

![](http://blog.adnansiddiqi.me/wp-content/uploads/2018/12/docker_phpinfo-1024x395.png)<figcaption>Web page inside docker in action<br></figcaption>

## Conclusion

In this <g id="6" data-gr-id="6">post</g> you learned how to install and setup docker and make it available for building PHP based websites. You should feel comfortable in setting up your own docker image, even if it not based on PHP. In the next <g id="7" data-gr-id="7">post</g> I will be discussing Docker compose and how to <g id="8" data-gr-id="8">use </g>`docker-compose.yml`<g id="8" data-gr-id="8"> <g id="5" data-gr-id="5">file</g></g> to organize and run multiple service based containers.

Read the second part [Create your first PHP/MySQL application in docker](http://blog.adnansiddiqi.me/create-your-first-php-mysql-application-in-docker/)