Monday, August 13, 2018

Use Dockerfile and docker-compose

Prerequisites

I am using Docker toolbox in Windows OS. If you are using Windows10 professional, you can use Docker for Windows.

How to install and start Docker

This post explains how to install and start docker in windows.

Dockerfile

We will make an image that contains Nginx with CentOS from a Dockerfile. This is the Dockerfile:
# Most Dockerfiles start from a parent image.
# FROM *** indicates what base image you will use.
FROM centos:7

# Maintainer name
MAINTAINER john doe <johndoe@email.com>

# To use commands, use "RUN".
RUN yum -y update 
RUN yum install -y epel-release
RUN rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
RUN yum -y install nginx

# "COPY" copies files from a host machine's directory into the Docker image. 
# COPY path/to/host /usr/share/nginx/html

# "EXPOSE" specifies which port you will open.
EXPOSE 80

# CMD is used to start modules.
# For example: CMD ["command", "argument 1","argument 2"]
# The modules must run in foreground. 
CMD ["nginx", "-g", "daemon off;"]
# If you use Apache
# CMD ["httpd","-DFOREGROUND"]
# Please note that you are not recommended to use systemctl to control the services if you use Docker.
We will use this Dockerfile to build Docker images. Save this file in "/c/Program Files/Docker Toolbox/dockerfile/app" (or "C:\Program Files\Docker Toolbox\dockerfile\app" in host machine) as "Dockerfile". Please note that the location of Docker toolbox can be different depending on how you installed it. If the "dockerfile/app" directory in Docker toolbox folder doesn't exist, create the directory. 


Open Docker quick start terminal.
The command to make an image from a Dockerfile is "build". The command "build" is used this way:
$ docker build -t image-name:tag-name /path/to/dockerfile
So this command to build the image:
$ docker build -t test/nginx:1.0 ./dockerfile/app
This will execute what the Dockerfile says:

(Please note that, when you make a Dockerfile, usually you don't need to write eveything from scratch. Look for a similar Dockerfile on internet and edit its detail.)

Docker compose

The above is how to make an image or a container from a Dockerfile. But usually, when you use Docker, you need to use multiple containers together. To use multiple containers, we will use docker-compose so that we can use multiple Dockerfiles/images/containers together. Files of docker-compose is usually .yml. The file below is the docker-compose file:
version: '3'
services:
  nginx:
    image: test/nginx:1.0
    ports:
      - "80:80"
  mysql:
    image: mysql:5.7.18
    ports:
      - "3306:3306"
      - "11211:11211"
    volumes:
      - ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: root
This is using test/nginx:1.0 image that we made beforehand. Save this as "docker-compose.yml" in "/c/Program Files/Docker Toolbox" (or "C:\Program Files\Docker Toolbox" in host machine).
Then run this command:
$ docker-compose up -d
The images/containers test/nginx:1.0 and mysql will start in background. You can check it with this command:
$ docker ps
To check if nginx is working, you need to access the docker machine from your browser. To do so, check your docker machine's IP address by this command:
$ docker-machine ip
This will return the IP address. Mine was 192.168.99.100. So I will see the page from my browser like this:

Seems like it is working.

docker-compose buid

We used docker-compose to use an existing image but if you want to build an image, use this instead:
version: '3'
services:
  nginx:
    build: ./dockerfile/app
    ports:
      - "80:80"
  mysql:
    image: mysql:5.7.18
    ports:
      - "3306:3306"
      - "11211:11211"
    volumes:
      - ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: root
Then use:
$ docker-compose build
$ docker-compose up -d

What is different from Virtualbox/Vagrant?

Docker isn't a virtual machine but a configuration management tool. On the other hand, Virtualbox/Vagrant creates virtual machines.
If you use Docker, both of the production server and the development environment will be Docker. This makes deployment easier. Also you can use existing containers for other projects too because, even if each of the production servers uses different OS, the production environment is always Docker.
Virtualbox/Vagrant creates virtual machines in development environment. So whatever the production server is, you can make same environment on the virtual machine (by installing same modules and enabling same services in same OS). Usually Ansible, Chef and so on are used to automatically create same environment in virtual machines.
See this Stackoverflow question for more details.