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.

How to make an image/a container

What the goal is

We will use Docker and install Apache in container of CentOS 7. We will save the container as image for later use.

Install Docker toolbox in Windows

See this post to install Docker toolbox in Windows.

Pull CentOS 7 image

Double click on "Docker quick start" icon and after its boot, run the following command on the console:
$ docker pull centos
This command is to get the latest CentOS image. To get Cent OS 7 explicitly, use
$ docker pull centos:centos7
instead. For this time, we will pull the latest CentOS. After the pull command, we should have the latest CentOS image. Run the following to check what images were downloaded:
$ docker images

Seems like the "centos" image is there. Now run the following command to run the centos image's container and start its bash. (Container is a kind of a virtual server made by the image.)
$ docker run -i -t centos /bin/bash

[root@ffdb5501112c /]# (the container's bash started)
You can run "exit" to stop the bash (but you don't need to stop it yet). Or you can use docker's attach command to get the container's shell. See here.
OK, we have the bash to run commands on the CentOS 7 container now. Run the following commands to see information of the container:
[root@ffdb5501112c /]# uname -a
[root@ffdb5501112c /]# cat /etc/redhat-release

Install Apache

We started the container and its bash by this command:
$ docker run -i -t centos /bin/bash
On the bash, run the following command to install Apache to the container's virtual machine:
[root@ffdb5501112c /]# yum -y install httpd
And the virtual machine will install Apache. 


Save the state as image for later use

We have installed Apache in CentOS 7. We will save this container as another docker image for later use, which means we make "CentOS 7 + Apache" docker image. At first, exit the bash mode:
[root@ffdb5501112c /]# exit
Run the following command to see the container ID.
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                        PORTS               NAMES
5b49d3ec21fb        centos              "/bin/bash"         13 minutes ago
Exited (127) 14 seconds ago                       nervous_allen

The top of the list is the container ID, so seems like it is "5b49d3ec21fb". Run the following command to make the image from the container:
$ docker commit 5b49d3ec21fb centos7/apache
Now the image should have been saved! Check if it was really saved by this command:
$ docker images

The image was successfully saved. Now you can use the image anytime like this:
$ docker run -i -t centos7/apache /bin/bash

Delete Docker images

$ docker rmi [image name]

Docker images made by other people

Docker images are shared in Docker hub.

Build image from Dockerfile

You can also build image from Dockerfile. If you want to share an same environment in a team, share Dockerfile and build image from the Dockerfile.

Use multiple containers for Docker

If you use multiple containers for your environment, you can use Docker compose.

How to install Docker

Prerequisites

  • I'm using Windows8.

Install Docker toolbox for Windows

Get an installer for Docker toolbox from here: https://docs.docker.com/toolbox/toolbox_install_windows

Install Docker toolbox with the installer. Please don't forget to tick git for Windows if you don't have it. If you don't know what it is, tick it. If you already have virtualbox, you can untick virtualbox.

Use Docker toolbox

Double-click on the shortcut icon of Docker quick start terminal: 

 If you run it for the first time, it creates a virtual machine used for Docker engine on the Virtualbox. After that, you will login to the virtual machine. 

This message means a virtual machine called "default" is ready at IP:192.168.99.100. The IP address varies depending on the environment. From this virtual machine, you use Docker. To check if it really works, run this command on it:
$ docker run hello-world
If you see this, you successfully did it:
docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:ca0eeb6fb05351dfc8759c20733c91def84cb8007aa89a5bf606bc8b315b9fc7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

Commands of Docker

To create a virtual machine called "dev":
$ docker-machine create --driver virtualbox dev
To check all machines and their status:
$ docker-machine ls
To stop the virtual machine called dev:
$ docker-machine stop dev
To start the virtual machine called dev:
$ docker-machine start dev
To remove the virtual machine called dev:
$ docker-machine rm dev

Access the Docker via SSH connection

Check the IP to connect on the Docker toolbox:
$ docker-machine ip
192.168.99.100
You can use this IP to connect from Putty via SSH connection. The user name is "docker" and the password is "tcuser".

Shared folder

"C:\Users" in host windows machine is shared to "/c/Users" in guest machine by default. 

Stop the Docker's machine

You can stop the default machine by
$ docker-machine stop default