Skip to main content

Capítulo 3: Imagens Autorais 🚀

Até que enfim! Agora vamos aprender a criar nossas próprias imagens Docker. Com elas, podemos desenvolver containers personalizados e começar a dominar o poder do Docker. 💡

Dockerfile: A Receita Mágica 🧑‍🍳

Para criar nossas imagens, vamos utilizar um arquivo especial chamado Dockerfile. Isso mesmo, sem extensão e com esse nome exato! O Dockerfile contém uma linguagem de script própria e funciona como uma receita para a criação da imagem. E a imagem, por sua vez, é a base do container. Vamos aprender a criar uma imagem simples para um servidor Node.js.

Criando o Projeto

Abra um terminal e crie um diretório para o nosso exemplo. Dentro dele, crie o arquivo app.js com o código do nosso servidor:

const express = require("express");
const app = express();

const PORT = process.env.PORT || 3000;

app.get("/", (req, res) => {
res.send("Hello, Docker! 🚀");
});

app.listen(PORT, () => {
console.log(`Servidor rodando na porta ${PORT}`);
});

Em seguida, inicie o gerenciamento de dependências:

npm init

Você verá algo assim no final:

{
"name": "example-app",
"version": "1.0.0",
"main": "app.js",
"scripts": {
"test": "echo 'Error: no test specified' && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"express": "^4.21.2"
}
}

Agora, adicione o Express como dependência de desenvolvimento:

npx add-dependencies --dev express

O Dockerfile

Agora, vamos para a parte interessante! Crie um arquivo chamado Dockerfile que vai definir o que nosso container precisa para funcionar. O Dockerfile especifica desde a imagem base até as instruções para instalar dependências e executar a aplicação.

Crie o arquivo com o comando:

touch Dockerfile

Dentro dele, cole o seguinte conteúdo:

# Usa a imagem oficial do Node.js
FROM node:18-alpine

# Define o diretório de trabalho dentro do container
WORKDIR /app

# Copia os arquivos para o container
COPY . .

# Instala as dependências
RUN npm install

# Expõe a porta que o app irá rodar
EXPOSE 3000

# Comando para iniciar a aplicação
CMD ["node", "app.js"]

Agora, vamos destrinchar cada parte desse arquivo!

📝 Comentários

Tudo que vem após um # é um comentário e não afeta a construção da imagem. Use-os sempre que quiser explicar alguma coisa no seu script!

🛠️ Imagens Base

Ao criar nossa imagem, podemos herdar de outra imagem, como é o caso da imagem node:18-alpine:

FROM node:18-alpine

Isso cria um container com o Node.js já instalado. E você pode escolher qualquer outra imagem que atenda à sua aplicação!

tip

Dica: Sempre que possível, tente usar imagens alpine. Elas são mais leves, o que faz a construção do container ser mais rápida e eficiente!

📂 Definindo o Local de Trabalho

Dentro do container, a estrutura de pastas funciona como uma máquina virtual. Podemos definir o diretório onde as operações subsequentes ocorrerão:

WORKDIR /app

Isso significa que todas as operações subsequentes (como COPY, RUN, etc.) ocorrerão dentro do diretório /app.

📦 Inserindo Arquivos no Container

Para que os arquivos do nosso projeto cheguem ao container, usamos o comando COPY:

COPY . .

Isso copia tudo do diretório atual para dentro do container. Como definimos o diretório de trabalho como /app, os arquivos serão colocados lá.

🔧 Rodando Comandos

Quando estamos criando a imagem, podemos executar comandos no container. Um exemplo disso é a instalação das dependências:

RUN npm install

Esse comando roda dentro do container para instalar as dependências descritas no package.json.

🌐 Expondo Portas

Para que o container possa se comunicar com o mundo exterior, precisamos expor uma porta. No nosso caso, a porta 3000:

EXPOSE 3000

Assim, o container estará acessível através da porta 3000.

🚀 Definindo o Ponto de Entrada

Sempre que o container iniciar, podemos definir um comando que será executado automaticamente. Como estamos criando um servidor, queremos que ele inicie sempre que o container rodar:

CMD ["node", "app.js"]

Isso executa o comando node app.js quando o container for iniciado. A sintaxe é como se fosse uma lista (array), onde cada parte do comando é um item.

🚫 Ignorando Arquivos

Às vezes, não queremos que certos arquivos sejam copiados para o container. Crie um arquivo .dockerignore com o seguinte conteúdo:

node_modules
npm-debug.log

Isso garante que, por exemplo, a pasta node_modules não seja copiada para dentro do container. Temos um comportamento semelhante ao .gitignore.

🚧 Construindo a Imagem

Agora que temos o Dockerfile, podemos construir nossa imagem com o comando:

docker build -t my-node-app .
warning

Importante: O comando docker build -t <nome_da_imagem> . deve ser executado no mesmo diretório onde o seu Dockerfile está. Caso contrário, o Docker não encontrará o arquivo de construção. Se o arquivo não estiver no mesmo diretório, então podemos substituir o "." pelo caminho até o Dockerfile

Aqui, my-node-app é o nome da imagem e . indica que o Dockerfile está no diretório atual.

🛠️ Rodando o Container

Agora que nossa imagem está criada, podemos ver todas as imagens disponíveis com:

docker images

Para rodar o container, use o comando docker run:

docker run -p 3000:3000 my-node-app

Isso mapeia a porta 3000 do seu container para a porta 3000 da máquina local.


🎉 Parabéns!

Agora você tem um container personalizado rodando uma aplicação Node.js! Acesse sua aplicação em http://localhost:3000 e veja o "Hello, Docker!".


warning

Atenção: Lembre-se de sempre testar seu Dockerfile localmente antes de tentar usá-lo em um ambiente de produção. Isso ajuda a evitar surpresas.