Docker Notes

Taha El Bouffi
7 min readFeb 27, 2021

Every useful information you need to know about Docker

What is Docker?

  • Docker is the software used to build, run, and orchestrate containerized applications.
  • When we talk about containerized applications, we’re not talking about apps running inside a virtual machine.
  • A containerized application will run on its own context, using a minimum set of binaries.
  • Thanks to Docker we have several apps running; each of them has a single context, which does not share it with any other app. At the same time, all the apps are running on top of the Docker Engine, which is the layer responsible for providing an interface from the apps to the OS and vice-versa.
  • Any container itself is exportable, destroyable and immutable. That’s one of the most powerful features about Docker

What is a Docker Container?

  • A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another

What is Docker Images?

  • A Docker Image, in a logical way, is a container’s template.
  • A Docker Image contains all the instructions and binaries necessary to build and run whatever containerized app you want.
  • You can find docker images for any technology, language, or framework. All primary images are stored in a large repository called Docker Hub, which is the official image repository maintained by Docker.

Image commands

docker pull nginx
docker pull nginx:1.14.2
docker image ls
docker image and click tab to see other commands
docker image ls - a q
docker image rm img_nm_or_id docker rmi img_nm_or_id
docker image rm $(docker image ls -a -q)
docker rmi $(docker images -a -q)

Container commands

docker container ls docker container run --rm -p 80:80 --name myNginx nginx

  • docker container run is the docker instruction to run containers , you can write --help after it to check more details.
  • — rm this flag indicates the container will be deleted once is stopped. Otherwise, we’re going to have to remove it manually.
  • -p 80:80 indicates the ports to be published. The number before the colon is the port of your host machine. The number after the colon is the port used by the container. Thus, in this case, we are saying: direct the connections from port 80 from my machine to port 80 from the container, and vice-versa.
  • — name myNginx is giving our container the name “myNginx.” If we don’t indicate this, our container will default to a random name from the main Docker project contributors.
  • nginx is the name of the image, which is the only required parameter of the command.
  • we can yse othe args like -e env_var=some_env_var
  • -d to run in detached mode so the container will run on background

Containers Management

docker ps -a
docker container <action> <container_name>
docker container restart myNginx
docker container stop myNginx
docker contaimer start myNginx
docker container rm -f myNginx
docker container rm $(rm container ls -a -q)
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

Running commands inside a container

docker container exec -it myNginx bash

  • -it makes possible to interact with the bash. The letter “i” is for making our shell interactive and “t” is for getting the output from that shell (TTY).
  • myNginx is the name of the running aimed container.
  • bash is the command name we want to use. In this case, since we want to get access to the shell, we need to use the command bash.

Once we run this command, we will see the Unix terminal of our nginx server. Here we can do anything. We can list directories, navigate through the filesystem, create new files or directories, check the processes running, etc. As an example, let’s create a new HTML file using this Unix command:

echo "<h1>Hello New File</h1>" >> /usr/share/nginx/html/new.html<br>

Now if we go to http://localhost/new.html, we will see the content of our new file. If we want to exit the bash, we can enter “exit,” and we’ll be out.

Keep in mind; not all images offer a “bash” option. They might have different ways to get access to the shell though. For example, in “alpine” images, you can access the shell with the command “sh” Take into account that you don’t need to get shell access to perform many actions.
Remember, you can always use “exec” with whichever command you want to use. Example:
docker container exec myNginx ls

Storage in Docker

By using Storage in Docker we can persist data or files from the host system into our containers and vice-versa. To achieve this, we can either use Bind Mounts or Volumes.

  • Bind Mounts: are used to storing files and directories into the container. Most of the time you will use them for your project files.
  • Volumes: are used to persist data. You will use them for your Databases.
  • So in short words: Use Bind Mounts for your project files and Volumes for your data.

Using bind mounts with an Nginx container

we want to bind the html folder on host machine to specific path on container

docker container run --rm -p 80:80 --name myNginx -v $(pwd)/html:/usr/share/nginx/html nginx

The main part is -v argument and the two Unix paths separated by a colon $(pwd)/html:/usr/share/nginx/html
The first path is $(pwd)/html indicates the directory from the host machine that we want to mount; the second one is the destination directory path in the container.
In a few words, what we are doing here is asking docker to:
Take whatever is inside the path: <my_current_position>/html from my host machine and mount it on the following containers path: /usr/share/nginx/html.
From now and on, any change you make on your HTML files from your host machine will be automatically reflected on the HTML files from your container.

Using Volumes with a Mongo image

One of the characteristics of Docker containers is its “destroyable” nature, which means, we can delete any containers quickly without leaving any tracks behind, this is useful for many situations, but for some situatoins we need to persist data, the solution is “Volumes”
Volumes are specific units of storage managed by the Docker engine, which we can use to persist any required data. Most of the database images out there already have volumes configured by default. However, here we will learn to create our custom volumes and use them in our DB containers.

  1. docker container run -d --name myMongo mongo
  2. docker container inspect myMongo
  3. docker volume ls
  4. docker volume create my-mongo-volume
  5. docker container run -d -v my-mongo-volume:/data/db --name myNewMongo mongo
    we also use this time include a -v option, and we use the volume’s name that we created before my-mongo-volume. The part after the colon represents the destination path of the container — where the volume will be mounted. In this case, we want to mount a volume to persist our data, so we use the /data/db path.

Networks in Docker

So far, we have been dealing with a single container at the time. But we all know that’s not how real applications work. Nowadays, a minimum stack project consists of an API, a frontend app, and a Database entity — as to give the most simple example. We might also talk about a microservices architecture with many artifacts running simultaneously. How can we connect all these pieces using Docker?
If you want to connect two or more containers, so that they can communicate with each other, they have to share the same network. In Docker, there are multiple ways to achieve this, but not all of them are good.
In general, when it comes to choosing how our containers will be talking to each other, we have Good, Bad and Ugly ways:

  • The Good: creating a specific bridge network. We are going to focus on this one.
  • The Bad: publishing all the required ports and running the containers with the — net=”host” option. Please, don’t do this!
  • The Ugly: Using the “link” option ( — link). It still works, but it’s planned to be removed soon.

For our example, we will connect a PHP-apache and a MySQL container using a bridge network.

Connecting two containers on the same network

Let’s start by first creating the network we want to use:

docker network create my-network

We can list the networks to verify the past command was successful using docker network ls

Now let’s start a PHP-apache container and link it to our new network created. We use the --network option for this:

docker container run -d --rm --network my-network --name php-server php:apache

Now it’s time for the MySQL database:

docker container run -d --network my-network -e MYSQL_ROOT_PASSWORD=123456 --name mysql-db mysql

At this point, these two containers should be able to communicate with each other.
To confirm this, we can use the command ping inside one of our containers.
Let’s get shell access into the PHP instance first:

docker container exec -it php-server bash

Unfortunately, this container doesn’t have available the ping command. So we need to install it:

apt-get update && apt-get install iputils-ping

After installing the ping tool inside the PHP container, we can proceed to ping the MySQL instance, using its container’s name. We should be able to see the ping responses.

ping -c 3 mysql-db

We will see, the container’s name will resolve to the container’s IP from your custom network. Which means the containers are connected.

--

--

Taha El Bouffi

Full Stack JavaScript Developer Experienced in NodeJS, Express, MongoDB, React, etc.