Introduction

Docker is a container manager for applications to easy develop, deploy and run diferent environments to be able to help the Developers and SysAdmins to manage big infraestructures. Docker use images to create environments to run them like a "Virtual Machine" allocated in a system sharing the host hardware. I wrote duble quotes on Virtual Machine because during the guide you will see that some of the feature that give this technology is based on Virtualization but others not. For now you only have to understand that Docker images are running as an individual process that have an ammount of RAM, hard drive space and processor cores to do the specific task that is assigned to that image.

Docker Containers diagram

Run command

Starting from the basics of how to initialize a Docker container using an existing image the first command is "docker run [imageName]" which download a image (if that image is not already in local machine) from hub.docker.com and start running the image inside a container. For interactive processes (like a shell), you must use "-it" in order to allocate a tty for the container process otherwise the container will shutdown if there is no process running.

docker run -it [imageName]

In case that we need to run a Web Server like Ngxinx inside a container, we can use directly the Nginx image using the comand "docker run -d -p 8081:80 --name nginx-server3 nginx"

  • -d: detach the container from the shell,
  • -p: map the container inner port (8081) to the host port (80) speared by ":",
  • --name: set to the current docker container a name (otherwise the name will be autogenerated).
docker run -d -p 8081:80 --name nginx-server3 nginx 

Container commands

One of the main commands we will use to view the Docker running containers is "docker ps" if we set the flag "-a" we can view all the Docker containers inclusive the ones that are shutdown.

docker ps -a

In case we need to review information of our containers we can use the command "docker inspect [containerName]" this command will return a Json with all the information of that Docker container, is important to understand that the container name also can be replaced with the CONTAINER_ID. Here we have also a flagh which is "-f '{{json .jsonProperty}}'" that retrieve the information of the property that we are defining in the path.

It's important to know that Docker is developed in GoLang so we can use that programming language to power up our interaction with the tool.

docker inspect edf98e996241 -f '{{json .Config}}'

Once a container have been running and we want to delete it from our system we can use the command "docker rm [CONTAINER_ID]". One more useful flag for this command is "-f" which allow us to force delete an image no matter if is currently running.

docker rm -f image-name

Already running containers

One of the most useful commands for Docker is "docker exec -it [containerName] bash" that opens the bash process inside the container defined and we will be able to interact with the image using the bash sell (only if bash is available inside that container).

docker exec -it [containerName] bash 

Manage data

To manage the data with Docker we can do it in three different ways, the first way is using

  • mounting points in our operating system where we can easy access to that data from the host machine and see all the information as it is stored,
  • volumes that are directly managed by Docker and this is the way we should do it because we have a lot of commands to interact with that volumes and is managed by Docker,
  • temfs is a way to store data directly in the memory that maybe we do not want to persist it and this data will be deleted when the image is deleted.

Types of mount

Mounting points

To use mount with Docker containers we can use the flag "-v [hostRoute:containerRoute]" to assign a host directory directly to a mounted volume inside the container. The next command will download the MongoDB official image and will mount the path C:\mongodata under the container path \data\db inside the mongo container.

docker run --name mongo-db -d -v C:\mongodata:\data\db mongo

Volumes

In case we want to use volumes first of all we need to create that volume using the command:

docker volume create [volumeName]

With the next command we can see the list of available volumes in our host machine:

docker volume ls

If we want to delete only one docker volume we can use

docker volume rm [VOLUME_NAME]

To delete the existent volumes that is not in use anymore we can use:

docker volume prune

Finally a practical example, after defining a volume if we want to use that volume inside a new mongo container we can just use the flag "--mount src=[volumeName],dst=[imageRoute]" with the name of an existent volume and the route where we want to mount it.

docker run -d --name db --mount src=[volumeName],dst=[imageRoute] mongo

Networking

First of all we need to understand that Docker manage networks virtualizing them. This virtual networks are managed as phisical networks but they live only inside the Docker context. To view the current networks the command is:

docker network ls

To create crete networks in Docker we should use the next command where the flag "--attachable" indicates that can attach manually the containers to this network.

docker network create --attachable [networkName]

To add containers to the network:

docker network connect [networkName] [containerName]

To see the network information:

docker network inspect [networkName]

The practical exercise here is to run a container exposing an inner port (container port) to the virtual network and by the end of the command we set the imageName that we want to run inside the container with the previous configured name.

docker run -d --name [containerName] -p [exposedPort]:[innerPort] [imageName]

Dockerfile

The Dockerfile is the way we create Docker images, all docker images are created by layers of different Dockerfiles. That means when we are trying to create a new Docker image it take advantage of the other Dockerfiles that are created in the Docker hub repository and we can use them to create our own image (like commits tree in Git).

Docker file structure

The content of a Docker file can be as simple as next example where we use

  • FROM to define the image we want to use as base for our new image and the
  • RUN will execute the defined command to run inside the image.

This Dockerfile create a increment of the ubuntu image with a file named hello-world under the path /usr/src

FROM ubuntu

RUN touch /usr/src/hello-world

Once we know how to create Dockerfiles we need to build the container image, this is easy using the following command docker build -t ubuntu:hello-world ., what we are doing here is to build the Dockerfile which is located in the same path as we are executing the command that's why we use . this path, also we asign the tag ubuntu:hello-world which will be the tag reference to our new image.

docker build -t ubuntu:hello-world .

In case we need to distribute this image we can push the image in our own Docker hub repository using the command docker push [dockerHubUserName]/ubuntu:hello-world, where we specify the repositoryName/imageName:tag. Docker hub have a free version where you can push whatever image you want, in case you need private repository you have to pay for it.

docker push [dockerHubUserName]/ubuntu:hello-world

Dockerfiles examples

  1. This example can be used as most standard NodeJs environment to start developing
  • FROM first of all use as base the NodeJs version 12 image,
  • COPY then copy everything from the host current dir into the image route,
  • WORKDIR move the prompt tot he route,
  • RUN execute the command to install all the dependencies,
  • EXPOSE expose the docker container inner port outside the machine,
  • CMD finally execute the command to start the node environment with the index.js file.
FROM node:12

COPY [".", "/usr/src/"]

WORKDIR /usr/src

RUN npm install

EXPOSE 3000

CMD ["node", "index.js"]