Getting started with Docker and Docker Compose

This Tutorial will set you immediately on the right path to start build docker containers of your own. In case you are new to Container, take a look at the Tutorial Everything you you need to know about container and Images
We will be looking at:

  1. Basic Docker commands
  2. How to create a custom docker image using docker commit
  3. How to create a custom docker image using Dockerfile
  4. How to push images to Docker Hub (Docker Registry)
  5. Docker Compose (How to create docker-compose.yml file)
  6. Docker compose workflow
  7. Docker Networking
  8. Brief on Docker Swarm

To desplay all images found on your local machine

docker images

To start a container from an images (e.g from a busybox images and run a command in the container)

docker run <image>:<tag> <any command you wish to execute in that container when it is stated>

Example: docker run busybox:1.29 echo "Hello World!"

To start a container from an images (e.g from a busybox images and run a command in the container) in the Background (detached mode)

docker run -d <image>:<tag> <any command you wish to execute in that container when it is stated>

To show all runing containers

docker ps

To show all containers that has previously run

docker ps -a

To go into the container in an interactive mode

docker run -i -t <image-name or image-id> OR docker run -it <image-name or image-id>

To start and remove the container when it finished run

docker run --rm <image>:<tag> <any command you wish to execute in that container when it is stated>

To inspect a runnung container in detached mode

Recall that when you run a container in detached mode by specifying -d the terminal returns to us the running container’s id. To inspect this container:

docker inspect <container-id>

To run a command in a running container

docker exec -it <container-id> <specify the command to run>

This inspection gives us information about the container like IP address, MAC address, image id, log path, status etc

To run an image like Tomcat and expose it to the host in another port

Recall that tomcat image runs by default in port 8080 in the container. to expose tomcat to the hosting OS in port 8888 we used:

docker run -it -p <host-port>:<conatiner-port> tomcat:9.0

Example: docker run -it -p 8888:8080 tomcat:9.0

After running the above command, go to your browser and run http://host-ip-address:8888 it should take you to the tomcat server runing in your docker container

To see the logs of a running container

docker logs <container-id>

To check the full set of image layers that make up an image

docker history <image>:<tag>

How to create a custom docker image using docker commit

In this section,

  1. We will pull and run the debian image from docker repository (docker hub)
  2. We will install git into the the runing container.
  3. Finally we will package/commit this container into a new docker image.

The ideal is to have a debain image with git installed.

Let’s get started

We will pull and run the debian image from docker

docker run -it debian:jessie

We will install git into the the runing container. In the interactive mode install git using:

apt-get update && apt-get install -y git

Finally we will package/commit this container into a new docker image.

docker commit <container-id> <repository-name>:<tag>

Remember to get container-id use docker ps -a and select the container id of the debain conatiner

The repository-name is the username of the docker registry/new-image-name e.g eddytnk/debian

You can now start a container based on this new image. Example: docker run -it eddytnk/debian-git:1.00

How to create a custom docker image using Dockerfile

Dockerfile is a text file that contains all the instructions users provide to assemble a docker image. Each instruction will create a new layer to the image.

A Dockerfile must not have any extension and must be name Dockerfile

How to write instruction in the Dockerfile

The first instruction must be a specification of the base image e.g

FROM debian:jessie

The next instruction must be the RUN command to execute when building the image is started

FROM debian:jessie
RUN apt-get update
RUN apt-get install -y git

Building the docker image with docker build command

Save your Dockerfile and open the terminal to the directory of the Dockerfile.

specify the docker build command

docker build -t <repository-name>:<tag> <path-to-Dockerfile>

Example docker build -t eddytnk/debian-git:1.00 .

dot (.) because I am in the current directory of my Dockerfile

More on Dockerfile

You can specify one RUN command with multiple instruction

FROM debian:jessie
RUN apt-get update && apt-get install -y \
    git \
    python \
    vim 

CMD Instruction

You can specify the CMD instruction using a Dockerfile. CMD Instruction is the instruction that runs when the container is started. If you don’t specify the CMD instruction in the Dockerfile, docker will use the default command defined in the based image.

For debian:jessie, the default command is bash.

Remember, the CMD instruction does NOT run when building the image, it only runs when the container starts up.

Example:

FROM debian:jessie
RUN apt-get update && apt-get install -y \
    git \
    python \
    vim 
CMD ["echo", "Hello Word!"]

COPY Instruction

The COPY instruction copies new files and directory from the build context and add them to the file system of the container.

FROM debian:jessie
RUN apt-get update && apt-get install -y \
    git \
    python \
    vim 
COPY myfile.txt /src/myfile.txt

The example Dockerfile will copy myfile.txt into /src/myfile.txt after the container is started

ADD Instruction

Simillar to COPY instruction but ADD allows you to download a file from the internet and copy to the conatiner when it is started.

ADD can automatically unpack compressed file

How to push images to Docker Hub (Docker Registry)

if you wish to change your image repository name and tag name

docker tag <image-id> <new-image-name>:<tag>

Remember to use docker images to get your image-id.

To push your image to docker hub your first need to login to docker hub using:

docker login --username=<docker-hub-id> then provide your password.

then you do: docker push <repository-name>:<tag>

Example: docker push eddytnk/debian-git:1.00

Docker Compose

This is a tool for defining and runing multi-container docker applications. We define all the containers in a single file called docker-compose.yml file and run a single command to start up all the containers

How to create docker-compose.yml file

  1. We specify the version, as of these write-up we have version: '3'
  2. We specify the services that make up our application. for each service, we provide instruction on how to build the container.
  • Service name,
  • build: path-to-Service-Dockerfile
  • ports: defines ports to expose to external network define in <host:container> format
  • depend_on: shows the serivices/ conatiners that should be started before our applicaion conatainer

We will define two services to be run on two containers as example in the file below dockerapp and redis

docker-compose.yml file

version: '3'
services:
    dockerapp:
        build: .
        ports:
            - "5000:5000"
        depends_on:
            - redis
    redis:
        image: redis:3.2.0

To run the instruction in the yml file, we use docker-compose up this will start the dockerapp container and the redis container and link them. Meaning the dockerapp container application can discover the redis conatiner

Docker compose workflow

  • Start containers: docker-compose up -d -d is to run in detached mode
  • Stop all runing containers without removing them : docker-compose stop
  • To remove all containers : docker-compose rm
  • To Rebuild all the images created from the dockerFile : docker-compose build. use to avoid docker-compose stop and docker-compose rm then docker-compose up pattern. This is common when we make changes in a container setup and we want to rebuild the containers from the beginning
  • Check status of containers managed by docker-compose: docker-compose ps
  • Check contianer’s log: docker-compose logs <container-name>

Docker Networking

Containers can communicate in three different network

None Network

The container is closed and cannot communicate to the outside world. Your application will be unable to make connection to the internet or any other network To start a conatiner in a None Network we use

docker run -d --net none <image-name>:<tag>

Bridge Network

This is the default network model in docker containers. All the conatiners on thesame bridge network can connect with each other and can connect to the outside world via the bridge network interface. Docker create a default bridge network called bride with the docker daemon is started.

Container within a different bridge network can’t access each other.

To create a bridge network we use

docker network create --driver bridge <bridge-network-name>

To list out all networks

docker network ls

Host Network

It is adds a container on the host’s network stack.Containers deployed on the host stack has full access to the host’s interface. This type of containers are called Open Containers

To start a container with host network

docker run -d --net host <image-name>:<tag>

To define docker network through docker compose file, let edit our docker-compose.yml file and added the networks field same level as services. We then set the netork name to the different services

version: '3'
services:
    dockerapp:
        build: .
        ports:
            - "5000:5000"
        depends_on:
            - redis
        networks: 
            - my_network
    redis:
        image: redis:3.2.0
        networks: 
            - my_network
networks:
    my_network:
        driver: bridge

Docker Swarm

This about scaling docker for large application. What if you have an application which consist of multiple containers which cannot fit into a single host? docker swarm provide solution for this question.

We have a swarm manager which managers multiple docker daemon running on different host. when you run a service, the swarm manager decide which daemon to run this service. You just need to point your docker client to the swarm manager instead of each an every docker daemon.

Learn more about Docker swarm in the article Docker swarm 101 – A Quick guide to learning docker swarm

No Responses

Leave a Reply

Your email address will not be published.