Docker
Why docker?
Imagine that you are developing an application that runs a few different services:
- Web Server in Node
- Database in MySQL
You want to send your application to someone to test. For that so, you need to deliver the source code. Let's create a person named Mark :older_man:.
The first problem is that Mark don't know how to install and run applications. So you need to go at his house and install it for him.
Another problem is that was tricky to install a few dependencies on Mark's computer, because he was using an different OS than yours. Ok, you had a hard time but it's all settled: let's run the application.
Oh no! You see some errors logged at the console. That's due to incompatibility issues between the dependencies you're using and the services you've installed. You installed the latest version of your services at Mark's computer, but you're using older ones in your personal computer, because you've been developing this application for a while.
:older_man: | You | |
---|---|---|
OS | Windows | Linux |
Node | 15 | 14 |
MySQL | 8 | 5.7 |
And it's not only about the versions, some dependencies you're using in your own computer doesn't exist for Mark's OS.
Wow, what a mess. What do you do? You can't predict all these problems as you're developing.And this is not an isolated case. It happens a lot. But how to cope whith these situations?
...
Bring the person at your house to show them! Don't you ever listen to the sentence: "It works on my computer"?
I'm kidding. Docker is the answer! (But you probably knew that I was going to say that at some point)
To summarize, docker solves these problems:
- incompatibilities
- long and difficult setup time
- different development and test environments
What is docker?
Simply put, docker is a software that allows you to separate your applications from your infrastructure, running each service with its own dependencies in separated containers.
Images
Image is like an recipe that give instructions to create a docker container.
Images can be based on another image, with some additional customization. Using the example given above, let's assume that your OS is an ubuntu
. You can create an image based on ubuntu
, and install Node and MySQL to it to run your application.
Dockerfile
Dockerfile is a file with simple syntax that define the steps needed to create the image and run it.
Example
FROM node:15-alpine
WORKDIR /var/www
COPY *.json .
COPY *.lock .
RUN yarn
COPY . . # add node_modules no .dockerignore
CMD ['yarn', 'start']
Each instruction creates one layer:
FROM
creates a layer from the node:15-alpine Docker image.COPY
adds files from your Docker client’s current directory.RUN
builds your application with yarn.CMD
specifies what command to run within the container.
MySQL will later be added in docker_compose file
Container
Container is a runnable instance of an image.
By default, a container is relatively well isolated from other containers, but it can be changed.
A container is defined by its image and any additional configuration options you set before creating or starting it.
Docker registry
Stores Docker images. Oftenly you pull the images of the repository, but you can also push your own container image and then the community will be able to have access to it.
Docker Hub
It's a public registry of container images.
Commands
docker run {image:tag}
Runs a container from an image
image
can be any image you want, such asubuntu
ormysql
tag
is where you specify the version of the image, such aslatest
or4.0.1
. If you don't specify any tag, docker will take the latest
Docker firstly will search the image locally. If the image is not found, it will search at the Docker Hub.
docker run -i {image:tag}
Runs a container in interactive mode. It means that you can provide inputs to the container you are running.
docker run -t {image:tag}
Runs a container printing out the output of the container.
docker run -it {image:tag}
It's a combination of running a container in interactive mode and showing the terminal output.
docker run -p {host_port:doccker_port} {image:tag}
If you want to have access to your application in a web browser for example, that is running in a container, you have to map the port you're using inside the container to a port in the docker host.
Then, you can access it by using the IP of the Docker Host, and the host_port
you have settled.
docker run -v {outside_container: inside_container} {image:tag}
Let's suppose you're running a database, and you want to persist the data, even if the container is deleted.
If you want to persist data, you have to map a directory outside the container on docker host, to a directory inside the container.
docker volume create {volume_name}
Create a volume
docker run -e {ENVIRONMENT_VARIABLE=value} {image:tag}
Sets an value for an environment variable accepted by the container.
To see the available environment variables, you have to run the inspect
command, and in the Config section there's a list of environment variables.
docker ps
Lists all running containers.
docker ps -a
List all containers, running or not.
docker inspect {container}
List all the details of a container in a JSON format.
docker logs {container}
Show the output provided by the application running in the container
docker stop {container}
Stops a running container.
container
can be the name of the container, or it's IP
You don't need to type that huge container IP number. The first 4 numbers is enough
docker rm {container}
Removes the container permanently
docker images
Lists all images and their sizes
docker rmi {image}
Removes an image
You need to ensure that aren't running containers using that image. You must stop and delete all containers using that image before deleting it.
docker pull {image}
Only downloads the image, without running a container.
docker build Dockerfile -t {tag_name}
Creates an image based on the instructions written on the Dockerfile. The -t
is to provide an tag_name for the image.
docker push {tag_name}
Uploads an created image on the Docker Hub
docker run --link {name_container:host_name} {image:tag}
Link two containers together
docker run --cpu={number} {image:tag}
Limits the CPU usage from a container
{number}
is an decimal number between 0 to 1, such as .5
docker run --memory={number}m {image:tag}
Limits the memory usage from a container
{number}
is any number, given in megabytes
Docker Compose
In order to run numerous services at once, Docker allows you to write a docker-compose.yml
file where you create configurations for the images you want to run.
docker-compose up
Runs all the images described at the docker compose.
Here is an example of the content of a docker-compose.yml
version: 3
services:
app:
container_name: app
command: sh -c "yarn && yarn start"
build:
context: .
dockerfile: dockerfile
volumes:
- .:var/www
ports:
- 3333:3333
depends_on:
- db
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
volumes:
db_data: