Docker
Manual de Uso
O que é um container?
"Um container é um padrão de unidade de software que empacota código e todas as dependências de uma aplicação, fazendo com que a mesma seja executada rapidamente de forma confiável de um ambiente computacional para outro." - Fonte: docker.com
Como funciona?
- Criação de ambientes isolados (container);
- Containers expõe portas para comunicação;
Principais conceitos
- Imagem (serviço disponível, exemplo: SQL, Postgres, REdis)
- Container (instância de uma imagem)
- Docker Registry (Docker Hub)
- Dockerfile:
- Receita de uma imagem
Comandos
Para listar todos os containers que estão rodando
$ docker ps
Para listar todos os containers (incluindo os que não estão rodando)
$ docker ps -a
Para parar um container usa-se $ docker stop NOME_DO_CONTAINER
, exemplo:
$ docker stop database
Para iniciar um container parado, usa-se:
$ docker start NOME_DO_CONTAINER
Para rodar um container
$ docker run --name nginx -d -p 8080:80 nginx# A flag -p serve para redirecionar a porta localhost para a porta do container# A flag -d significa detached, para que o container não fique preso ao terminal# A flag --name serve para nomear o container
Acessando e alterando arquivos de um container
$ docker exec -it nginx bash# A flag -it representa a interação com o container# O comando "exec" representa a execução do comando para com o próprio container# O comando "bash" aponta que deverá rodar o bash dentro dele
Bind mounts
O bind mount serve para montar um container com arquivos pré definidos, por exemplo: Ao carregar um container Nginx, o exemplo abaixo montará o arquivo index.html (localhost:8080) com um arquivo index.html pré setado localmente:
$ docker run -d --name nginx -p 8080:80 -v ~/Desktop/PESSOAL/Cursos/fullcycle/docker/bind-mounts/:/usr/share/nginx/html nginx
De forma segura (sem criar a pasta localmente):
$ docker run -d --name nginx -p 8080:80 --mount type=bind,source="$(pwd)",target=/usr/share/nginx/html nginx
Trabalhando com volumes
Para criar um volume:
$ docker volume create meuvolume
Para listar os volumes:
$ docker volume ls
Para inspecionar um volume:
$ docker volume inspect meuvolume
Para criar um container apontando para um volume em específico:
$ docker run --name nginx -d --mount type=volume,source=meuvolume,target=/app nginx# ou$ docker run --name nginx -d -v meuvolume:/app nginx
- Caso seja criado um segundo container usando o mesmo volume, ele compartilhará as informações pré existentes
Para limpar os volumes
$ docker volume prune
Entendendo imagens e DockerHub
As imagens ficam armazenadas no Docker Registry, ou Docker Hub. Lá contém as versões (sendo estas latest ou releases fixas).
Para consultas as imagens existentes na máquina, deve rodar o comando:
$ docker images# OUTPUT:## REPOSITORY TAG IMAGE ID CREATED SIZE# ubuntu latest a7870fd478f4 33 hours ago 69.2MB# nginx latest 8f05d7383593 11 days ago 134MB# hello-world latest 46331d942d63 2 months ago 9.14kB
Para baixar uma imagem para a máquina
$ docker pull php
Com uma tag específica
$ docker pull php:rc-alpine
Para excluir imagens
$ docker rmi php:latest # É necessário incluir a tag
Para publicar uma imagem no Dockerhub deve rodar o comando:
$ docker push nomedaimagem
Criando serviço de Banco de dados Postgres:
https://hub.docker.com/_/postgres
Inicialização:
$ docker run --name database -e POSTGRES_PASSWORD=docker -p 5432:5432 -d postgres:11
Ao finalizar, exibirá o id do container
Dockerfile e Docker Compose
Arquivo Dockerfile
É o arquivo de configurações que executará os comandos iniciais do conteiner.
Para rodar o Dockerfile, basta rodar o comando abaixo no terminal:$ docker build -t usuario-no-dockerhub/nginx-com-vim:latest .# A flag -t representa Tag
Tipos de network
- Bridge
- Host
- Overlay
- Maclan
- None
Para listar as networks:
$ docker network ls
Para matar as networks não utilizadas:
$ docker network prune
Para criar uma rede deve rodar o seguinte comando:
$ docker network create --driver bridge minharede
Criando um container com a rede criada
# Exemplo$ docker run -dit --name ubuntu1 --network minharede bash
Acessando o container e descobrindo o IP
$ docker exec -it ubuntu1 bash$ bash-5.1# ping ubuntu2 # Só funcionará com a rede previamente criada, caso contrário deve rodar: $ ip addr show
Conectando um container em uma rede
$ docker network connect minharede ubuntu3# minharede: Nome da rede# ubuntu3: Nome do container
Criando um container com a network Host
$ docker run --rm -d --name nginx --network host nginx
Container acessando nossa maquina
$ docker run --rm -it --name ubuntu ubuntu bash# Dentro do container, pode rodar o comando abaixo para acessar a máquina local (exemplo utilizando o curl)$ curl http://host.docker.internal:8000
Criando aplicação Node sem o Node
Com o Docker é possível rodar uma aplicação sem ter o framework instalado de fato. Com o exemplo abaixo, será replicado na pasta pwd
(current folder) o que acontece na pasta usr/src/app, ou seja, se lá dentro estiver rodando uma aplicação Node.js, assim será feito na pasta ./ (pwd)
.
$ docker run --rm -it -v $(pwd)/:/usr/src/app -p 3000:3000 node:15 bash
Otimização utilizando Multistage Building
Exemplo de um comando de build usando multistage (para produção)
$ docker build -t user_dockerhub/project:prod laravel -f folder/Dockerfile.prod
Exemplo:
# Imagem de referênciaFROM node:alpineRUN mkdir -p /home/node/api/node_modules && chown -R node:node /home/node/apiWORKDIR /home/node/apiCOPY package.json yarn.* ./USER nodeRUN yarnCOPY --chown=node:node . .CMD ["yarn", "start"]EXPOSE 3001
Docker compose
Arquivo docker-compose.yml
É o arquivo que instancia o conteiner.
Exemplo:
version: '3.6'networks:minhanetwork:driver: bridgeservices:meubackend: # Nome do conteinerbuild:context: .dockerfile: Dockerfileimage: nodejscontainer_name: meubackend # Chamada do conteinerrestart: unless-stoppedenv_file: .envports:- "3001" # Porta ouvida pelo conteinervolumes:- .:/home/node/apinetworks:- minhanetworkcommand: yarn start # Comando executado para rodar o serviço
Criando banco de dados MySQL
# docker-compose.ymlversion: '3'services:db:image: mysql:5.7command: --innodb-use-native-aio=0container_name: dbrestart: alwaystty: truevolumes:- ./mysql:var/lib/mysqlenvironment:- MYSQL_DATABASE=nodedb- MYSQL_ROOTPASSWORD=rootnetworks:- node-networknetworks:node-network:driver: bridge
Dependência entre containers
No docker-compose.yml
é possível incluir o parâmetro depends_on
e passar o nome de uma imagem de dependência. Além disso, é possível utilizar o Dockerize como comando para aguardar um container terminar de ser montado para um outro iniciar. Por exemplo:
# docker-compose.ymlversion: '3'services:app:build:context: nodecontainer_name: app# Entrypoint usando o dockerize abaixoentrypoint: dockerize -wait tcp://db:3306 -timeout 20s docker-entrypoint.shnetworks:- node-networkvolumes:- ./node:/usr/src/apptty: trueports:- "3000:3000"# Exemplo de depends_on abaixodepends_on:- db
Arquivo .dockerignore
Arquivo responsável para ignorar arquivos/pastas não requiridas para execução do projeto
Exemplo:
node_modules