Guia introdutório de Docker
Importants commands docker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// pull image
docker pull ubuntu
// list all open containers
docker container ls
// list id's containers
docker ps -q
// list all containers
docker containers -a
//list images
docker image ls
//list all images
docker image ls -a
// remove all images
docker rmi $(docker images -q)
// remove one image
docker rmi name_image
// init container
docker start name_container
// stop all cotainners
docker stop $(docker ps -aq)
// run one container attached the terminal to it
docker run -it name_image
// stop one container
docker stop (name or id)
// remove container
docker rm (id or name) -f // (-f if it was running)
// remove all containers stoped
docker container prune
// run one container with port and name and dettached
docker run -d -p 80:8080 --name server nginx:latest
// add network in create container
docker network create --driver bridge local
// stop the current container and remove it after get out
docker-compose down --rmi all
// backup mysql in container
docker exec container_mysql_name /usr/bin/mysqldump -u root --password=root schema > backup.sql
// util image web containers
docker run --name postgres11 -e POSTGRES_PASSWORD=docker -p 5432:5432 -d postgres:11
// run one mongo container
docker run --name mongo -p 27017:27017 -d -t mongo
// run one detached mysql container
docker run --detach --name=mysql8 -p 3306:3306 --env="MYSQL_ROOT_PASSWORD=docker" mysql:8.0.22
// remove all
sudo rm -rf /var/lib/docker
// para inspecionar informações importantes do container
docker container inspect mysql8
// para pausar um container
docker container pause mysql8
// para despausar um container
docker container unpause mysql8
Docker Register[PT-BR]
Imagine o cenário, precisamos configurar uma imagem pessoal para subir um container em um determinado servidor, com o doker hub podemos facilmente ter images pessoais privadas(plano não gratuito no docker hub), assim podemos usa-las quando e onde quisermos, grandes datacenter também vão ter seus próprios registers, por exemplo digamos que temos uma conta na digital ocean, basta termos nosso register privado lá e conseguiremos ter nossas images privadas para subir em nosso servdor remoto, configurar um github actions ou uma pipeline para fazer essa integração não é uma tarefa complicada.
Binds e mounts
Muitas vezes removemos os containers após o uso.
É muito comum usar o container e apagá-lo após o uso, dessa forma os dados desse container são perdidos e nesse ponto entram os volumes ou mount que permitem salvar dados fora de um container.
Volumes são usados para os dados não serem removidos ao paramos nosso container, trata-se de um mapeamento entre seu host (computador de trabalho) e container, em alguns projetos que temso a necessidade de fazer um apontamento de arquivos que não serão perdidos entre nossa maquina e algum container.
Utilizando volumes
1
docker run -d --name nginx -v ~/ti/testdocker/html:/usr/share/nginx/html -p 8080:80 nginx
No exemplo acima apontamos um volume de nossa maquina local por meio da tag -v para dentro da pasta do nginx, dessa forma se perdemos nossa imagem o conteúdo estará salvo no host.
A forma mais atual de se trabalhar com volumes é utilizando mounts, um exemplo de diferença entre volumes e mounts é que volumes criam pastas em nosso host mesmo que essas não existam, mounts não.
Utilizando bind e mount
1
2
3
docker run -d --name nginx --mount type=bind,source=/Users/andremartds/ti/testdocker/html,target=/usr/share/nginx/html -p 8080:80 nginx
docker run -d --name nginx --mount type=bind,source="$(pwd)",target=/usr/share/nginx/html -p 8080:80 nginx
Caso você utilize $(pwd) esse comando vai conseguir pegar o diretório absoluto de onde você está no momento.
Volumes
Pode ser que precisemos ter um volume centralizado em nosso host e queremos apontar esses dados para um ou mais containers, nesse caso tudo que for criado em um container será apontado para os outros que compartilham desse type.
requer estar na mesma rede*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# commands
docker volume
# create volume
docker volume create my_volume
# list every volumes in your register
docker volume ls
# remove volumes
docker volume prune (hash volume)
# inspect volumes
docker volume inspect myvolume
Criando e utilizando um volume
1
2
3
4
5
6
7
8
9
10
11
# cria um volume
docker volume create my_volue
# rodando uma imagem e atrelando nosso novo volume com -v
docker run -d -p 8082:80 --name nginx24 -v my_volume:/app nginx
// ou
docker run -d -p 8080:80 --name nginx1 --mount type=volume,source=my_volume,target=/app nginx
//e
docker run -d -p 8081:80 --name nginx2 --mount type=volume,source=my_volume,target=/app nginx
// acessando o container para criar um arquivo
Acessando e alterando arquivos de um container
Para acessar um container ativo precisamos utilizar o docker exec
1
2
docker exec nginx ls //lista os diretorios da pasta root do container
docker exec nginx -it bash // acessa o container com nosso bash local
Agora que acessamos nosso container vamos alterar o arquivo index do nginx
1
2
3
4
5
6
7
8
9
cd /usr/share/nginx/html
apt update
apt install vim
vim index.html // altere seu arquivo html
// use i para inserir
// :q para sair
// :wq para sair e salvar
// esq para parar de inserir
Perceba o conceito images, elas são IMUTÁVEIS ou seja, caso nosso container seja removido ao reutilzarmos a imagem que temos em nossa máquina a mesma virá sem as alterações que acabamos de fazer
Criando images com Dockerfile
A partir de um Dockerfile (receita de uma imagem) conseguimos definir diversas configurações extras para nosso container, imagine que você precisa de volumes, redes portas e ainda precisa utilizar isso para subir posteriormente para um servidor e utilizar.
O Dockerfile é um facilitador pois nele podemos definir muitas características e comandos para nosso container.
Primeira imagem com Dockerfile
crie em um diretório um arquivo com o nome Dockerfile
1
2
3
FROM nginx:latest
RUN apt update
RUN apt install vim -y
agora que criamos nossa primeira imagem vamos construi-la para ficar salva em nosso register local.
1
2
3
docker build -t andremartds/nginx-com-vim .
# ou
docker build -t qualquer_nome_desejado .
No comando acima nós construimos nossa imagem com as características que colocamos no nosso arquivo Dockerfile, ou seja adicionamos o vim ao nginx
1
docker container run -it andremartds/nginx-vim-example bash
agora que criamos a imagem podemos executar a mesma.
Comandos úteis para um Dockerfile
vamos nos basear neste Dockerfile e descrever os comandos abaixo.
1
2
3
4
5
FROM nginx:latest
WORKDIR /app
RUN apt update
RUN apt install vim -y
COPY html /usr/share/nginx
Criando um diretório de trabalho dentro de um Dockerfile, ao logar no container já iniciaremos neste diretório /app
1
workdir /app;
Copiando de uma pasta do nosso computador para dentro do container
1
2
3
COPY html /usr/share/nginx
// html em nosso computador
// /usr/share/nginx nosso caminho dentro da imagem para o nginx
para executar comandos no docker podemos utilizar o CMD, esse comando é mais utilizado para o ponto final de execução, comandos comuns é mais utilizado o comando RUN
1
2
3
4
5
FROM ubuntu:latest
workdir /app
CMD ["echo", "hello world"]
no exemplo acima criamos uma nova imagem baseada no ubuntu, adicionamos o diretório de trabalho e posteriormente adicionamos o CMD
1
docker build -t andremartds/ubuntu-test .
da forma acima iremos criar a imagem, o ponto significa que estamos no diretório onde se encontra o Dockerfile
1
docker run --rm andremartds/ubuntu-test echo 'oi oi'
agora perceba que no exemplo acima estamos reescrevendo a saída do CMD, essa é a uma das funcionalidades do CMD.
1
docker run -it andremards/ubuntu-test bash
é da mesma forma, ao executarmos o comando acima ele faz uma substituição do que existe dentro da imagem para podemos executar e acessar diretamente um container
CMD vc ENTRYPOINT
1
2
3
4
5
6
7
FROM ubuntu:latest
WORKDIR /app
ENTRYPOINT [ "echo", "Hello " ]
CMD [ "world" ]
O grande ponto da image acima é que nela temos o entrypoint e o cmd, pense que o cmd pode servir tanto para executar comandos mas também serve para enviar parametros para o entrypoint.
1
2
3
4
5
docker build -t andremartds/ubuntu123 .
docker run --rm andremartds/ubuntu123 // retorna Hello world
docker run --rm andremartds/utuntu123 oioi // retorna Hello oioi
Acessando entrypoint.sh
Por muitas vezes vemos containers que acessam arquivos de shell, basicamente esses arquivos são executados a partir do nosso comando
1
ENTRYPOINT["docker-entrypoint.sh"];
então dentro de nossa image temos uma chamada para esse arquivo, ao final desse arquivo podemos ter o seguinte.
1
2
//cat docker-entrypoint.sh
exec "$@"
com essa entrada acima vamos poder executar CMD posteriormente em nossa dockerfile ou linha de comando
Publicando images no Dockerfile
o primeiro passo é criar a nosso arquivo html para jogar dentro do nginx - index.html
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>Dedev é lindo</h1>
</body>
</html>
agora na mesma pasta vamos definir nosso Dockerfile
1
2
3
4
5
6
7
FROM nginx:latest
COPY html /usr/share/nginx/html
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
No exemplo acima baseamos nossa image na image do nginx, e por isso trazemos algumas características dela para dentro do nosso container, adicionamos o entrypoint e o CMD, outro ponto a se notar nesse arquivo é que estamos fazendo uma copia de html para dentro do html do nginx.
agora vamos subir nossa imagem
1
2
3
4
5
6
7
docker build -t -d andremartds/nginx-personalizado
docker login
// usuario e senha de seu hub.docker.com
docker push andremartds/nginx-personalizado
Pronto, como o register do docker é publico então a imagem está disponível para download na internet, da seguinte forma.
1
docker run andremartds/nginx-personalizado
Networks no docker
Tipo de network
- Bridge O tipo de network mais comumn no docker é esse tipo, utiliza-se essa rede quando vamos fazer com que um container se comunica com outro
- Host Ele mescla a network do docker com a do host, ou seja tanto o host quanto o docker ficam na mesma rede
- Overlay para um container comunicar com outro em maquinas diferentes eles precisam estar nesse tipo de rede, também é utilizado pelo docker swarmer
- Maclan
- none sem rede, de forma isolada
Network bridge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
docker network // lista os comandos do network
docker network ls // lista todas as redes
docker network prune // mata todas as networks que nao estão sendo utilizadas
// criando um rede
docker network create -d bridge my-bridge-network
// criando container atrelado a rede
docker run -d -it ubuntu1 --network minharede
docker run -d -it ubuntu2 --network minharede
docker run -d -it ubuntu3
// conectando um container a network
docker network connect minharede ubuntu3
docker inspect network minharede
// acesse seus containers e instale
apt-get update
apt-get install iputils-ping
agora basta acessar pingar para ver a conexão entre os containers
docker exec -it ubuntu1 bash
ping ubuntu2
// outro terminal
docker exec -it ubuntu2 bash
ping ubuntu1
Network host
com essa rede basicamente conseguimos atrelar a rede do docker ao nosso host, vamos ao exemplo.
1
docker run -d --it --name nginx --network host nginx
dessa forma tanto o container quanto o host terão o mesmo host
Acessando container em nossa maquina
Fazendo com que o container acesse a nossa maquina atravéz de uma porta, é um pouco estranho isso. mas podemos precisar desse recurso.
digamos que temos um node rodando na porta 3333, por algum motivo precisamos acessar esse cara de dentro do nosso container, vamos aos passos para isso.
1
2
3
// rodando nosso node no host local, digamos que nosso projeto está na porta 3333
npm run dev
// app rodando na 3333
Nesse ponto vamos acessar nosso container que precisa acessar esse recurso
1
2
3
docker run -it ubuntu
# curl http://host.docker.internal:3333
Dessa forma conseguimos acessar o nosso host, ou seja. bastaria puxar uma rota e seguir a vida acessando por exemplo uma entrada a uma api
Conteúdo abaixo está desorganizado ‘ainda’
// example of Dockerfile FROM node:latest MAINTAINER andremartds/mynode COPY . /var/www // copia do . para /var/www WORKDIR /var/www // diretório de trabalho RUN npm install // comando para rodar o node e instalar ENTRYPOINT npm start // ponto de entrada EXPOSE 3000 // expomos a porta 3000
// … other behaviors
para rodar esse container é muito simples, com o docker ativo no seu computador execute
1
docker build -f Dockerfile
esse comando vai criar uma imagem a partir do Dockerfile
Sign register
Vamos logar na nossa conta e enviar o nosso container
1
2
docker login
docker push nome_usuario/nome_image
enviamos a imagem para o docker hub
Docker Compose
Vamos compor um docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
version: '3'
services:
nginx:
build:
dockerfile: ./docker/nginx.dockerfile
context: .
image: douglasq/nginx
container_name: nginx
ports:
- "80:80"
networks:
- production-network
depends_on:
- "node1"
- "node2"
- "node3"
mongodb:
image: mongo
networks:
- production-network
node1:
build:
dockerfile: ./docker/alura-books.dockerfile
context: .
image: douglasq/alura-books
container_name: alura-books-1
ports:
- "3000"
networks:
- production-network
depends_on:
- "mongodb"
node2:
build:
dockerfile: ./docker/alura-books.dockerfile
context: .
image: douglasq/alura-books
container_name: alura-books-2
ports:
- "3000"
networks:
- production-network
depends_on:
- "mongodb"
node3:
build:
dockerfile: ./docker/alura-books.dockerfile
context: .
image: douglasq/alura-books
container_name: alura-books-3
ports:
- "3000"
networks:
- production-network
depends_on:
- "mongodb"
networks:
production-network:
driver: bridge
Agora vamos buildar esse yml
1
2
3
4
5
6
// docker compose
docker-compose build
// -d dettached
docker-compose up -d
// stop compose rellationships in this yml
docker-compose down
docker build de fato constrói o container
docker compose up sobe todos os containers relacionados ao build pré feito
docker-compose down para todos os container relacionados ao yml