Você está na página 1de 3

# Usando docker build e docker commit

São dois métodos para que a gente possa criar as nossas próprias imagens, porém
elas possuem algumas diferenças que vamos apresentar mais para frente.
## Docker Commit
É um processo simplificado para realizarmos testes. Com ele, é possível suprir a
necessidade da volatilidade dos containers, ou seja, agora eu consigo ter meus
dados persistidos.
Mas ela traz uma grande desvantagem, pois toda vez que eu preciso fazer uma
alteração na minha imagem, eu necessito recarregar ela, eu preciso restartar o
container(ou o processo mesmo)

- Assim, o passo a passo para a criação da minha imagem seria:


- Ter um container temporário
- Fazer as alterações que eu preciso docker commit
- Gerar novos containers a partir daquela imagem.

- A sintaxe do comando é: `docker commit options container repo`, onde:


- **docker commit**: é o comando em si para fazer o deploy da imagem
- **options**: são as flags ou opções que temos
- **container**: é o nome do container
- **repo**: é o nome do novo repositório que estamos criando
- A convenção é sempre adotar o formato: nomerepo/nomeimagem:versão

## Docker Build
O docker build é uma grande forma de criarmos ambientes em produção. A ideia dele é
automatizar a criação de imagens e é um processo baseado em instruções. O mais
interessante é que ele funciona basicamente como uma grande documentação do
ambiente
já que utiliza o arquivo **Dockerfile** para configurar o ambiente.

Para montar nossa imagem, vamos precisar criar um arquivo simples chamado
Dockerfile com alguns comandos
```
FROM debian
RUN apt-get update
RUN apt-get install apache2 -y
```

Pronto!! Agora, basta buildar a nossa imagem com o comando `docker build -t
nome_que eu_desejo_minha_imagem`. A opção -t é para tag da imagem

Depois, basta startar o nosso container normalmente com o comando `docker run -d --
name nome_do_container -p 8080:80 minha_imagem usr/sbin/apache2ctl -D
FOREGROUNDcutr`

Um detalhe interessante é que algumas imagens já possuem um comand args rodando e


não precisam utilizar uma instrução ao fim do comando

Qualquer alteração no Dockerfile é necessário que a gente dê um `docker build`


novamente

### DockerFile
- **FROM**: É a imagem que base do nosso container
- **RUN**: Permite a execução de comandos do tipo shell script. Esses comandos
podem ser escritos de duas formas: shell form ou json syntax. Veja o exemplo de
ambos abaixo.
![aaa](imagens/plain-stringXjson.png)
- **COPY**: Cópia arquivos do diretórios atual do host(build context) para dentro
da imagem. `Ex: COPY ./ app`
- **WORKDIR**: Instrui onde estão localizado o meu diretório de trabalho para criar
instruções do tipo RUN, CMD, ENTRYPOINT, COPY.
```
# Saída do pwd - a/b/c
WORKDIR /a
WORKDIR b
WORDIR C
RUN pwd
```
- **EXPOSE**: define um socket para coneSxão que deve ser exposto quando a imagem
for buildada. Ou seja, ainda precisamos do comando docker run -p ou -P para
informar quais são as portas
```
EXPOSE 80/tcp
EXPOSE 80
```
- **VOLUME**: Ele informa quais serão os volumes a serem mapeados, assim eliminando
a necessidade de usar o `docker run - v VOLUME`
```
VOLUME /var/www/html
VOLUME /data
```

Por padrão, algumas imagens vem com uma instrução padrão para ser executada como as
base images que vem com o /bin/bash, o do apache que vem com um ele como comando
padrão em foreground. Elas simbolizam o motivo dessas imagens existirem, porém
essas instruções podem ser rescritas

Assim, podemos estabelecer uma diferença entre o entrepoint e o CMD


- **CMD**: É um comando executado por padrão em um container docker. Ele é a razão
de existir daquele container, o propósito para o qual aquele container foi criado.
Nós podemos modificar essa instrução também.
+ Para o `CMD` nós temos duas formas de chamar o comando, através da forma do
*shell* `CMD ps aux` ou pela forma mais comum(e otimizada) que é o *exec form*,
passando diretamente o binário que eu gostaria de executar e seus parâmentros `CMD
["usr/bin/ps, "aux"]`

- **ENTRYPOINT**: É como o próprio nome diz: é um ponto de entrada. É um comando em


execução dentro do container, mas que espera uma instrução de entrada quando ele é
iniciado. Um belo exemplo disso são os containers de banco de dados que por padrão
esperam que você passe a senha de root para eles. Então, os containers dessas
aplicações(ou binários) sempre esperam que você passe para eles um comando daquela
aplicação e não outro.
+ Com o **Entrypoint**, podemos definir um comando padrão para o nosso container,
ou seja, definir o que ele irá executar assim que for inicializado e depois podemos
definir **CMD** para aquele binário em execução.

Nós temos algumas formas de fazer o **CMD**. Veja as formas de executar


![](imagens/docker-entrypoint.png)

```shell
docker run --rm -it --name c1 --entrypoint ps wesle-araujo/entrypoint2:1.0 aux

docker run --rm -it --name c1 wesle-araujo/entrypoint:1.0


docker run --rm -it --name c1 wesle-araujo/entrypoint2:1.0 google.com

docker build -t wesle-araujo/entrypoint2:1.0 -f entrypoint/entrypoint_ping2 .

```

## Boas práticas para um Dockerfile

- **Efemeridade**: Todo container tem por obrigação ser algo extremamente


descartável para e que não precisamos nos preocupar em guardar os seus dados dentro
da nossa imagem. Ele pode ser parado, reconstruído e substituído a partir dos seus
arquivos de configuração.
- **Twelve-factors app**: Toda aplicação deve ser executada de maneira stateless(ou
seja, ela não deve guardar estados). Todos os dados devem ser armazenados de
maneira externa em uma base de dados(docker volume)
- **Build context**: É o diretório onde está o meu Dockerfile. Temos que nos
atentar para dois fatores.
+ O fato do nosso diretório ser específico e criar uma separado para criar os
nossos arquivos Dockerfile. Se criarmos um Dockerfile em uma pasta que nós temos
muitos arquivos que não iremos, o docker irá entender que todos aqueles arquivos
são potencialmente para uso e assim não teremos
+ Quanto maior for o conteúdo do nosso Dockerfile, maior serão as etapas de
build, push, pull e também o nosso container.
- **Redução da complexidade**: Redução da complexidae e do tamanho dos arquivos,
ganhamos em tempo de criação.
- Cada container deve executar apenas um processo por vez.
- Sempre que possível diminua a quantidade de layers sempre utilize a concatenação
de comandos para agilizar o processo de build. Alguns exemplo de comandos que criam
layers intermediária: RUN, COPY e ADD.
- Não trabalhar com a latest

##

https://github.com/docker/compose/releases/download/X.XX.XX/docker-compose-`uname -
s`-`uname -m` -o /usr/local/bin/docker-compose

https://github.com/docker/compose/releases/tag/v2.17.1/docker-compose-linux-x86_64

https://github.com/docker/compose/releases/download/v2.17.1/docker-compose-linux-
x86_64

Você também pode gostar