Docker run para Docker Compose: converta um comando em arquivo
Muita imagem no Docker Hub ensina a subir o container com um docker run cheio de flags. Funciona, mas é uma instrução que você precisa guardar e gerenciar do seu lado. Aqui eu converto esse comando em um docker-compose.yml, flag por flag, e deixo o servidor subindo sozinho quando a máquina religa.
Gravei essa aula em 10 de novembro de 2023, com o servidor de build TeamCity, da JetBrains, numa EC2. A versão do arquivo e os comandos são os daquela data: antes de copiar, confira a documentação oficial do Compose e a referência do arquivo, porque o formato pode ter mudado. Se você ainda não viu o básico do Compose, comece por Docker Compose na prática.
Por que sair do docker run
Num cliente em que faço consultoria, tivemos que montar um ambiente para rodar build, com o TeamCity, e as instruções de subida também estavam em docker run. Com o Compose, o mesmo ambiente fica num arquivo central e estruturado: você enxerga de uma vez o mapeamento de volume, a porta e tudo que o projeto precisa para rodar.
Tem ainda a rede. Ao subir com docker run, o Docker cria uma rede nos bastidores. Quando você sobe outro container, um banco para esse servidor de build, por exemplo, ele fica numa rede separada, e você precisa mapear isso na mão. O Compose faz esse gerenciamento, e ligar dois serviços fica bem mais simples. O arquivo também entra no versionamento do projeto.
Se você entende a conversão, entende o que está escrito no arquivo. Sem isso, o Compose só gera confusão no projeto.
1Preparar a EC2
Fiz tudo na AWS, partindo do zero, para você ver o ambiente rodando:
- Um security group chamado
aula docker mais docker compose, com SSH liberado só para o meu IP e HTTP (porta 80) para o mundo, porque o servidor de build sai pela porta 80. - Um par de chaves e uma instância
t3.micro, com disco de 12 GB. - No Advanced Details, no User Data, colei o script que instala o Docker. Ele está no meu projeto BIA no GitHub, na pasta
scripts. - Conectei o VS Code à instância por SSH. Esse passo está em Docker na AWS com VS Code Remote SSH. Lembre de dar
chmod 400na chave.pem.
2Ler o docker run da imagem
Na página da imagem jetbrains/teamcity-server no Docker Hub, o fabricante manda baixar a imagem e rodar este comando:

Cada pedaço dele tem um lugar no Compose:
No docker run |
No docker-compose.yml |
|---|---|
jetbrains/teamcity-server (a imagem, no fim) |
image |
--name teamcity-server-instance |
container_name |
-p <porta-no-host>:8111 |
ports |
-v ...:/data/teamcity_server/datadir e -v ...:/opt/teamcity/logs |
volumes |
3Montar o arquivo
Crie o docker-compose.yml na pasta do usuário, a /home/ec2-user. Comecei pela versão e pelo serviço, que é um só neste exemplo:
version: "3"
services:
teamcity-server:
image: jetbrains/teamcity-server
restart: always
container_name: teamcity-server-instance
ports:
- 80:8111
volumes:
- data_dir:/data/teamcity_server/datadir
- logs:/opt/teamcity/logs
Linha a linha:
image: a imagem que estava no fim do comando.container_name: o nome que o--namedava ao container.ports:80:8111mapeia a porta 80 da máquina para a 8111 do container. No navegador, basta o IP da instância.volumes: o comando tinha dois-v, um para os dados e outro para os logs. Dei um nome a cada um,data_direlogs, e do lado direito vai o caminho que a imagem usa dentro do container.restart: always: não existia no comando da página. Se a EC2 for parada à noite para economizar e ligada no dia seguinte, o servidor sobe sem eu fazer nada.
4Dizer onde ficam os volumes
Se você não declara os volumes, o Docker coloca os dados no caminho padrão. Eu quis saber onde ficam os meus dados, até para fazer backup. Então declarei os dois no fim do arquivo, com o driver local e um bind para uma pasta minha:
volumes:
data_dir:
driver: local
driver_opts:
type: none
device: /home/ec2-user/teamcity/datadir
o: bind
logs:
driver: local
driver_opts:
type: none
device: /home/ec2-user/teamcity/logs
o: bind

O arquivo completo ficou com a versão, o serviço, a imagem, o nome, a porta, os volumes e o restart.

5Subir e corrigir o erro das pastas
Na pasta do arquivo:
docker-compose up -d
Um comando só baixa a imagem e sobe o container. Na página da imagem, o docker pull e o docker run aparecem como dois passos.
Na minha primeira tentativa deu erro: falha ao montar o volume, porque eu ainda não tinha criado as pastas do device. Criei as três e subi de novo:
mkdir teamcity
cd teamcity
mkdir datadir
mkdir logs
Voltei para a pasta do arquivo e rodei docker-compose up -d outra vez.
O container teamcity-server-instance ficou de pé na porta 80. Na primeira vez o servidor demora um pouco para iniciar. Se a página não abrir, use http:// e não https://: eu tentei com HTTPS e não carregou.
6Entrar, ver o log e testar o restart
Dois comandos que o Compose facilita:
docker-compose exec teamcity-server /bin/bash
docker-compose logs
O primeiro abre um terminal dentro do container do servidor. O segundo mostra o log, onde vi o servidor iniciando.
Depois parei a instância, esperei ficar como parada e liguei de novo. Ao conectar e rodar docker ps, o servidor do TeamCity já estava no ar, sem eu subir nada. É o restart: always fazendo o trabalho. Na Formação mostro como automatizar a parada com uma Lambda e um agendamento, para você não pagar pela máquina à noite.
Um detalhe que apareceu: o IP público da instância mudou depois de ligar de novo, e tive que atualizar o endereço da conexão. Sem Elastic IP, isso acontece. O ideal é nem depender de IP público: a conexão por Session Manager (SSM) usa o ID da instância, que não muda.
Checklist
- Leia o
docker runda imagem e separe: imagem,--name,-pe cada-v. - Crie o
docker-compose.ymlcom um serviço e traduza cada flag:image,container_name,ports,volumes. - Se quer saber onde ficam os dados, declare os volumes no fim do arquivo, com
driver: localeo: bind. - Crie na máquina as pastas que o
deviceaponta antes de subir. - Acrescente
restart: alwayspara o servidor voltar sozinho quando a máquina religar. - Suba com
docker-compose up -de acompanhe comdocker psedocker-compose logs. - Prefira a conexão por SSM a depender de IP público: o ID da instância não muda.
Com o comando convertido em arquivo, o ambiente sobe com um comando, volta sozinho depois de uma parada e ligar outro serviço, como um banco, fica mais simples do que com docker run.
O que os alunos dizem

“Eu queria voltar para a área técnica, mas aprender AWS sozinho só me deixava frustrado.”
William Santos, Tech Lead
Ver depoimento
“Eu sempre fugi da AWS. Achava complicado, distante da minha rotina de dev. Mas só a primeira aula do Bootcamp já mudou tudo: usei o conteúdo para resolver um problema real de um cliente e fui contratado por causa disso.”
André Scherrer, Engenheiro de Software
Ver depoimento
“Só quando coloquei a mão na massa com a Formação AWS é que avancei de verdade. Essa prática me levou ao próximo nível”
Caio, Desenvolvedor (Dev)
Ver depoimento
Formação AWS
Aprenda AWS e IA na prática, com projeto real e acompanhamento. Converse com o time sobre a Formação AWS.
Agende uma conversaPrefere assistir?
A aula completa (34 min) está no canal Domine AWS. O vídeo toca aqui mesmo.

