Domine inglês técnico de programação em 2025, seja qual for seu nível. Inscrição gratuita

Dockerfile: Principais comandos para criar a receita da imagem Docker
Thiago Marinho

Thiago Marinho

5 min de leitura
docker

Navegação Rápida:

    Vamos aprender os principais comandos utilizados no Dockerfile.

    Introdução

    Dockerfile, como vimos neste post, é responsável por criar nossas imagens. Podemos dizer que ele é a receita que essa imagem vai seguir. É com esse arquivo que podemos gerar o build e criar o container a partir dele.
    Para criar um Dockerfile é simples, basta criar um arquivo com o nome Dockerfile.
    Para gerar a imagem a partir do Dockerfile, executamos o comando abaixo no mesmo local que o arquivo se encontra:
    docker build -t nome_da_imagem .
    Para criar o container a partir dessa imagem construída, podemos executar o comando:
    docker run nome_da_imagem

    FROM

    Instrução obrigatória que indica qual imagem vai ser utilizada como ponto de partida. Podemos  criar uma imagem a partir de uma imagem do Node.js ou um sistema Linux usando uma imagem do Ubuntu e assim por diante. É possível criar sua própria imagem usando a instrução FROM scratch.
    FROM node:12-alpine
    O comando acima indica que será criado uma imagem com Node.js.

    RUN

    Serve para executar comandos no processo de montagem da imagem que estamos construindo no Dockerfile, ele é executado durante o build (construção da imagem) e não durante a construção do container. Em um Dockerfile é possível ter mais de um comando RUN.
    FROM node:alpine WORKDIR /usr/app RUN npm init -y RUN npm install cowsay RUN npx cowsay Hello Docker RUN cat package.json
    Quando rodamos o comando abaixo, podemos ver o log de cada RUN sendo executado no processo de criação da imagem:
    docker build -t nodej/nodej .
    Resultado:
    ❯ docker build -t nodej/nodej . Sending build context to Docker daemon 3.072kB Step 1/6 : FROM node:alpine ---> 0f2c18cef5d3 Step 2/6 : WORKDIR /usr/app ---> Using cache ---> 0399f14efe3b Step 3/6 : **RUN npm init -y** ---> Using cache ---> da2345d90786 Step 4/6 : **RUN npm install cowsay** ---> Using cache ---> bf6c1a19a89a Step 5/6 : **RUN npx cowsay Hello Rocketseat** ---> Running in 78f5486fa633 __________________ < Hello Rocketseat > ------------------ \\ ^__^ \\ (oo)\\_______ (__)\\ )\\/\\ ||----w | || || Removing intermediate container 78f5486fa633 ---> 02d9013dbf0b Step 6/6 : **RUN cat package.json** ---> Running in 675e768b4b16 { "name": "app", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \\"Error: no test specified\\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "cowsay": "^1.4.0" } } Removing intermediate container 675e768b4b16 ---> 260e87152b92 Successfully built 260e87152b92 Successfully tagged nodej/nodej:latest

    CMD

    Diferente do RUN, o CMD executa apenas na criação do container e não no build da imagem. Deve ser único no Dockerfile.
    FROM node:alpine WORKDIR /usr/app RUN npm init -y RUN npm install cowsay RUN npx cowsay Hello Rocketseat RUN cat package.json CMD npm start
    Execute o comando abaixo para recriar a imagem:
    docker build -t nodej/nodej .
    Depois rode o comando abaixo para criar o container:
    docker run -t nodej/nodej
    O comando vai criar a imagem e dentro do container será executado o npm start, porém no package.json não foi definido no script start, mas perceba que o CMD executou apenas no container e não na construção da imagem. E o log do erro só apareceu quando criamos o container.
    > docker run -t nodej/nodej npm ERR! missing script: start npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2020-08-20T17_40_32_268Z-debug.log

    EXPOSE

    Instrução que informa qual porta deverá ser liberada. EXPOSE não é um comando que libera a porta, ele serve para ficar documentado no Dockerfile quais portas deverão ser liberadas ao criar o container.
    Para efetivamente liberar a porta é preciso passar o parâmetro -p  no comando docker run, vamos ver a seguir.
    FROM node:alpine WORKDIR /usr/app RUN npm init -y RUN npm install cowsay RUN npx cowsay Hello Rocketseat RUN cat package.json EXPOSE 3000 ## informa que deverá ser liberado a porta 3000 na criação do container CMD npm start
    Execute o comando abaixo para criar o container e liberar a porta 3000:
    docker run -p 3000:3000 -d nodej/nodej
    Para liberar a porta usamos o parâmetro -p 3000:3000. Está sendo realizado também o redirecionamento de portas, onde o primeiro parâmetro 3000 é a porta do host e o segundo :3000 é a porta do  container. Isto é, toda vez que o host receber uma requisição na porta 3000, o container irá ouvir a requisição na porta 3000 também.
    notion image
    Liberando portas na aplicação: Porta 3000 Host e :3000 Container.
    Podemos liberar portas TCP e UDP, por padrão, quando não é especificado /tcp ou /udp, é liberado a porta TCP.
    docker run -p 80:80/tcp -p 80:80/udp ...
    Por padrão, a porta tcp é liberada quando não é especificado o protocolo, exemplo:
    docker run -p 8080:80

    COPY e ADD

    Comandos para copiar arquivos e pastas de um lugar específico na máquina local para uma pasta no container.
    Diferença é que ADD copia arquivos remotos para alguma pasta na imagem e também pode copiar arquivos compactados (tar.gz) que serão descompactados na imagem automaticamente.
    Por questões de semântica, sempre utilize COPY para copiar arquivos e pastas locais e ADD para arquivos remotos ou compactados. Utilize o ADD se realmente for necessário. Leia as boas práticas sobre COPY e ADD.
    Exemplos:
    Se quiser acompanhar em sua máquina, faça os seguintes procedimentos abaixo:
    • COPY
    Digite no terminal dentro de um diretório para criar um projeto com Node.js:
    yarn init -y
    Altere o package.json:
    { "name": "docker-node", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "node index.js" }, "keywords": [], "author": "", "license": "MIT" }
    Crie o arquivo index.js na raiz do projeto com o seguinte conteúdo:
    console.log("Qual é a soma de 2 + 2: ", 4);
    Crie o arquivo Dockerfile na raiz do projeto:
    FROM node:alpine WORKDIR /usr/app COPY package.json ./ COPY index.js ./ RUN npm install RUN cat package.json RUN npm start EXPOSE 3000 # CMD npm start
    Execute o comando abaixo no terminal e observe o log:
    docker build -t nodej/nodej .
    No final será impresso:
    Qual é a soma de 2 + 2 = 4
    • ADD
    Exemplo com o comando ADD:
    FROM ubuntu:18.04 RUN mkdir /myfolder WORKDIR /myfolder ADD /sample.tar.gz ./ RUN ls ## listando arquivos RUN ls project RUN ls -la RUN echo "FIM"
    Execute o comando abaixo e observe o log:
    docker build -t nodej/nodej .
    Será adicionado um arquivo compactado da máquina do host para o container recém criado dentro da pasta myfolder, em seguida o arquivo será descompactado automaticamente.

    VOLUME

    Quando adicionamos VOLUME no Dockerfile estamos informando um ponto de montagem, criando uma pasta que ficará disponível entre o container e o host.
    FROM ubuntu:18.04 RUN mkdir /minha_pasta RUN echo "hello world" > /minha_pasta/hello.txt VOLUME /minha_pasta
    Dockerfile acima define a utilização da imagem do ubuntu:18.04, cria uma pasta chamada minha_pasta e depois cria um arquivo hello.txt com o conteúdo "hello world" dentro da pasta, por fim é disponibilizado o VOLUME /minha_pasta para que o host tenha acesso.
    Podemos fazer espalhamento do Volume conforme podemos ver neste post.

    WORKDIR

    Define uma pasta dentro do container onde os comandos serão executados.
    FROM node:alpine WORKDIR /usr/app COPY package.json ./ RUN npm install CMD npm start
    Estamos definindo que na pasta usr/app serão executados os comandos seguintes, o arquivo package.json será copiado do host para user/app, inclusive o comando RUN npm install será executado dentro do contexto definido no WORKDIR.

    USER

    Podemos alterar os usuários para executar os comandos. No exemplo abaixo defini o usuário node para executar os comandos e, como não precisa de privilégios de super usuário (root), podemos usar usuário sem tantos privilégios.
    FROM node:alpine USER node ## definindo o usuário que realizar os comandos RUN whoami ## qual usuário está usando o terminal, será impresso node WORKDIR /usr/app COPY package.json ./ RUN npm install CMD npm start

    Conclusão

    Interessante observar a flexibilidade que temos quando criamos nossas imagens e containers com Docker.
    Vimos os principais comandos: FROM para definir uma imagem; RUN para executar algum comando no processo de build da imagem; CMD para executar algum comando após a criação do container; EXPOSE para documentar qual porta deve ser liberada na criação do container; COPY e ADD para copiar arquivos locais e remotos para o container; VOLUME para definir um local onde serão armazenados arquivos que serão compartilhados com o host; WORKDIR para definir um ponto de partida de onde os arquivos serão executados; e, por fim, o comando USER para definir qual usuário irá executar os comandos no container.
    No canal no youtube temos um vídeo sobre Deploy de aplicações NodeJS à AWS com Docker, que traz alguns conceitos mais avançados sobre essa ferramenta, assista:
    Video preview

    Links

    notion image
    E aí o que achou do post?
     
    Espero que tenha curtido! 💜
    O aprendizado é contínuo e sempre haverá um próximo nível! 🚀
    Marcadores

    Aprenda programação do zero e DE GRAÇA

    No Discover você vai descomplicar a programação, aprender a criar seu primeiro site com a mão na massa e iniciar sua transição de carreira.

    COMECE A ESTUDAR AGORA