Difference between revisions of "Docker"

From VeRLab Wiki
Jump to: navigation, search
(Testando Docker Rootless)
 
(51 intermediate revisions by 3 users not shown)
Line 1: Line 1:
==Instalação==
+
== Docker Rootless Mode ==
  
'''Importante''': para estas configurações é necessário que a máquina tenha um docker instalado com versão >= 20.10
+
O modo disponível do Docker para os usuários da rede é o '''Docker Engine no modo Rootless''', ou seja, apenas a versão em linha de comando e no modo de acesso non-root.
  
Este processo ainda se encontra em uma fase experimental e não está disponível em todas as máquinas. As máquinas disponíveis com docker até o momento são '''PROC6''', '''PROC7''', '''EVA''' e '''DALEK'''.
+
Em geral, funciona para todas as aplicações e pode-se ler mais informações no [https://docs.docker.com/engine/security/rootless/ link Docker Rootless]
 +
<br><br>
 +
'''Importante''': para estas configurações é necessário que a máquina tenha um docker instalado com versão >= 20.10 (pode ser conferido com: <code>docker version</code>)
  
===Configuração inicial===
+
Este processo ainda se encontra em uma fase experimental e não está disponível em todas as máquinas. As máquinas disponíveis com docker até o momento são '''PROC1, PROC2, PROC5, PROC6, PROC7, EPONA, NYMERIA, DROGON''', '''EVA, WALL-E, MAGRITTE''' e '''DALEK'''.
Para utilizar docker em uma máquina no laboratório é preciso que o usuário:  
+
<br><br><br>
 +
 
 +
== Modo 1(systemd): Configuração Docker rootless com Systemd (<span style="color: red">não é possível usar simultaneamente em outras máquinas, apenas em uma máquina da rede por vez</span>) ==
 +
 
 +
<br><br>
 +
A opção mais intuitiva para executar o Docker Rootless é gerenciando pelo '''systemctl --user'''. Porém tem a limitação de <span style="color: red;">'''funcionar em apenas uma máquina da rede por vez'''</span>, pois o arquivo que gerencia o systemctl do usuário é salvo na /home que é compartilhada em todas as máquinas, portanto '''apenas um processo docker rootless do usuário pode ser criado, mas em qualquer máquina da rede'''.
 +
 
 +
=== Pré-requisitos ===
 +
Para utilizar docker rootless em uma máquina no laboratório é preciso que o usuário:  
  
 
* solicite à equipe de rede para criar uma pasta de rascunho no disco local como /draft-xxx/nome_do_usuario e dar permissão de leitura/escrita.
 
* solicite à equipe de rede para criar uma pasta de rascunho no disco local como /draft-xxx/nome_do_usuario e dar permissão de leitura/escrita.
 
* solicite à equipe de rede a instalação do docker na máquina.
 
* solicite à equipe de rede a instalação do docker na máquina.
 +
<br><br>
  
 +
=== Configuração ===
 
Feito estas etapas, para configurar o acesso na máquina é preciso seguir os seguintes passos para executar o docker rootless:
 
Feito estas etapas, para configurar o acesso na máquina é preciso seguir os seguintes passos para executar o docker rootless:
  
Line 17: Line 29:
  
 
<code>echo '{"data-root":"/<path-em-disco-local>/<user>/docker-cache"}' | tee ~/.config/docker/daemon.json</code>
 
<code>echo '{"data-root":"/<path-em-disco-local>/<user>/docker-cache"}' | tee ~/.config/docker/daemon.json</code>
 
+
<br><br>
 
'''Importante:''' Lembre-se de ajustar o <code><path-em-disco-local>/<user></code> para uma armazenamento de rascunho na máquina e alguma pasta do seu usuário (por exemplo, <code>/draft-hdd/fulano</code>).
 
'''Importante:''' Lembre-se de ajustar o <code><path-em-disco-local>/<user></code> para uma armazenamento de rascunho na máquina e alguma pasta do seu usuário (por exemplo, <code>/draft-hdd/fulano</code>).
 
+
<br><br>
 
Esses dois primeiros passos são específicos para as máquinas do VeRLab: por padrão o Docker guarda arquivos na /home do usuário, mas essa pasta é compartilhada em rede (por NFS ou MooseFS) e o Docker não dá suporte a isso.[https://github.com/docker/for-linux/issues/1172 Aqui está um issue citando o problema]
 
Esses dois primeiros passos são específicos para as máquinas do VeRLab: por padrão o Docker guarda arquivos na /home do usuário, mas essa pasta é compartilhada em rede (por NFS ou MooseFS) e o Docker não dá suporte a isso.[https://github.com/docker/for-linux/issues/1172 Aqui está um issue citando o problema]
  
 
# Execute <code>dockerd-rootless-setuptool.sh install</code>.
 
# Execute <code>dockerd-rootless-setuptool.sh install</code>.
Importante: Após terminar, o comando vai pedir que você altere seu .bashrc para adicionar uma linha semelhante a <code>export DOCKER_HOST=unix:///run/user/<uid>/docker.sock</code> (varia por usuário). Faça essa alteração antes de prosseguir copiando e colando o comando no terminal.
+
<br><br>
 +
'''Importante''': Após terminar, o comando vai pedir que você altere seu .bashrc para adicionar uma linha semelhante a <code>export DOCKER_HOST=unix:///run/user/<uid>/docker.sock</code> (varia por usuário). Faça essa alteração antes de prosseguir copiando e colando o comando no terminal.
 
# Reinicie o Bash com <code>exec bash</code>.
 
# Reinicie o Bash com <code>exec bash</code>.
# Ative a inicialização automática do Docker: <code>systemctl --user enable --now docker</code> ou manualmente: <code>systemctl --user start docker</code>
+
# Ative a inicialização automática do Docker em seu usuário: <code>systemctl --user enable --now docker</code> ou manualmente: <code>systemctl --user start docker</code>
 +
 
 +
 
 +
Com isso, a configuração está pronta!
 +
 
 +
=== Utilização ===
 +
Comandos para confirmar se o Docker está funcionando:
 +
* Verificar status do docker daemon:  <code>systemctl --user status docker.service</code>
 +
* Parar docker daemon:  <code>systemctl --user stop docker.service</code>
 +
* Verificar configurações do Docker Rootless: <code>docker version</code>  ou  <code>docker info</code>
 +
* Baixar uma imagem teste e executá-la: <code>docker run hello-world</code>
 +
<br><br><br>
 +
 
 +
== Modo 2 (Manual): Configuração Docker Rootless "Manual" para <span style="color: red;">execução simultânea em várias máquinas da rede<span> ==
 +
 
 +
<br><br>
 +
Essa opção pode parecer menos intuitiva, pois o usuário precisará executar manualmente o '''daemon do docker rootless''' em um terminal e mantê-lo em execução para poder utilizar os comandos docker em outros terminais.
 +
 
 +
Isso pode ser facilmente feito utilizando os [https://www.verlab.dcc.ufmg.br/mediawiki/index.php/Trabalhando_remotamente#Usando_tmux_ou_byobu:_multiplexador_de_terminais  multiplexadores de terminal como tmux ou byobu].
 +
 
 +
Uma vez que parar a execução do docker daemon com ctrl+c ou fechar o terminal, isso vai "matar" a execução do docker rootless na máquina e parar todos seus containers de forma abrupta. Porém tem a flexibilidade de não precisar da pasta /home para armazenar as configurações do daemon, então <span style="color: red;">com essa configuração é possível executar o docker rootless em várias máquinas simultaneamente!<span>
 +
 
 +
=== Pré-requisitos ===
 +
Para utilizar Docker Rootless em uma máquina no laboratório é preciso que o usuário:
 +
 
 +
* solicite à equipe de rede para criar uma pasta de rascunho no disco local como /draft-xxx/nome_do_usuario e dar permissão de leitura/escrita.
 +
* solicite à equipe de rede a instalação do docker na máquina.
 +
 
 +
 
 +
 
 +
=== Configuração ===
 +
 
 +
# Abra seu arquivo <code>~/.bashrc</code> no editor de texto preferido, se for no terminal pode usar o nano: <code>'''nano ~/.bashrc'''</code>
 +
# Cole as seguintes funções no final desse arquivo e salve o mesmo:
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Adicionar funções no .bashrc para facilitar o uso do '''docker-rootless mode'''
 +
|-
 +
 +
<pre>
 +
# Funções para adicionar no final do arquivo ~/.bashrc e usar docker rootless na rede VeRLab/JLab
 +
# v4 mai/2025 by mauferrari
 +
 
 +
# Path para o diretório base a ser utilizado pelo docker rootless do usuário
 +
export USER_DOCKER_BASE_DIR=/draft-hdd
 +
 
 +
# Função para criar pastas e configuração do docker rootless
 +
function docker-rootless-create-dir(){
 +
  MYUSER=$(whoami)
 +
  # Cria environment variables para pastas
 +
  echo -e "Creating Docker Rootless Folder for user $MYUSER..."
 +
  export USER_BASE_DIR=$USER_DOCKER_BASE_DIR/${MYUSER}
 +
  export USER_DOCKER_DIR=$USER_BASE_DIR/docker-rootless
 +
  echo -e "  USER_BASE_DIR=$USER_BASE_DIR\n  USER_DOCKER_DIR=$USER_DOCKER_DIR"
 +
  # Verfica se o diretorio base do usuário existe
 +
  if [ ! -d "$USER_BASE_DIR" ]; then
 +
    echo -e "ERROR!\n  USER_BASE_DIR=$USER_BASE_DIR needs to be created by user '$MYUSER'!"
 +
    unset USER_BASE_DIR
 +
    unset USER_DOCKER_DIR
 +
    return 1
 +
  fi
 +
 
 +
  # Verifica pasta do usuário usada pelo docker rootless
 +
  if [ ! -w "$USER_BASE_DIR" ]; then
 +
    echo -e "ERROR!\n  USER_BASE_DIR=$USER_BASE_DIR needs to be writable by user '$MYUSER'!"
 +
    unset USER_BASE_DIR
 +
    unset USER_DOCKER_DIR
 +
    return 2
 +
  fi
 +
  # Verifica se a pasta do usuário já existe
 +
  if [ -d "$USER_DOCKER_DIR" ]; then
 +
    echo -e "ERROR!\n  USER_DOCKER_DIR=$USER_DOCKER_DIR already exists!"
 +
    echo -e "  Please remove it or use another folder!"
 +
    unset USER_BASE_DIR
 +
    unset USER_DOCKER_DIR
 +
    return 3
 +
  fi
 +
  # Cria pastas usadas pelo docker rootless
 +
  mkdir --parents $USER_DOCKER_DIR
 +
  export XDG_RUNTIME_DIR=$USER_DOCKER_DIR/.docker/run
 +
  export XDG_CONFIG_HOME=$USER_DOCKER_DIR/.config
 +
  mkdir --parents $XDG_RUNTIME_DIR
 +
  mkdir --parents $XDG_CONFIG_HOME/docker
 +
 
 +
  # Cria configuração do docker rootless
 +
  echo "{\"data-root\":\"${USER_DOCKER_DIR}/docker-cache\"}" | tee $XDG_CONFIG_HOME/docker/daemon.json  && \
 +
  nvidia-ctk runtime configure --runtime=docker --config=$XDG_CONFIG_HOME/docker/daemon.json
 +
 
 +
  echo -e "\n\n  HOME=$HOME \n  XDG_CONFIG_HOME=$XDG_CONFIG_HOME \n  XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \n  XDG_DATA_HOME=$XDG_DATA_HOME \n  DOCKER_HOST=$DOCKER_HOST"
 +
  echo -e "\n\ncat $XDG_CONFIG_HOME/docker/daemon.json\n" && cat $XDG_CONFIG_HOME/docker/daemon.json
 +
  echo -e "\n\nDocker Rootless Folders and Config Files Successfully Created!"
 +
}
 +
 
 +
# Função para iniciar manualmente daemon do docker no modo rootless
 +
function docker-rootless-daemon-run(){
 +
  MYUSER=$(whoami)
 +
  echo -e "Exporting Environment Variables for Docker Rootless Daemon..."
 +
  export USER_DOCKER_DIR=$USER_DOCKER_BASE_DIR/${MYUSER}/docker-rootless
 +
 
 +
  echo -e "  USER_DOCKER_DIR=$USER_DOCKER_DIR\n  XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR\n  XDG_CONFIG_HOME=$XDG_CONFIG_HOME"
 +
  # Verifica se o diretório do usuário existe e pode ser escrita pelo docker rootless
 +
  if [ ! -d "$USER_DOCKER_DIR" ] && [ ! -w "$USER_DOCKER_DIR" ]; then
 +
    echo -e "ERROR!\n  USER_DOCKER_DIR=$USER_DOCKER_DIR does not exist or is not writable!"
 +
    echo -e "  Please run docker-rootless-create-dir first!"
 +
    unset USER_DOCKER_DIR
 +
    return 1
 +
  fi
 +
  export XDG_RUNTIME_DIR=$USER_DOCKER_DIR/.docker/run
 +
  export XDG_CONFIG_HOME=$USER_DOCKER_DIR/.config
 +
  # Verifica se o daemon do docker rootless está rodando
 +
  echo -e "Checking Docker Rootless Daemon..."
 +
  if [ -S $XDG_RUNTIME_DIR/docker.sock ]; then
 +
    echo -e "ERROR!\n  Docker Rootless Daemon is already running at $XDG_RUNTIME_DIR!"
 +
    echo -e "  Please stop it first!"
 +
    unset USER_DOCKER_DIR
 +
    unset XDG_RUNTIME_DIR
 +
    unset XDG_CONFIG_HOME
 +
    return 2
 +
  fi
 +
  # Start docker daemon
 +
  echo -e "\n\n  HOME=$HOME \n  XDG_CONFIG_HOME=$XDG_CONFIG_HOME \n  XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \n  XDG_DATA_HOME=$XDG_DATA_HOME \n  DOCKER_HOST=$DOCKER_HOST"
 +
  echo -e "\n\ncat $XDG_CONFIG_HOME/docker/daemon.json\n" && cat $XDG_CONFIG_HOME/docker/daemon.json
 +
  echo -e "Starting Docker Rootless Daemon..."
 +
  dockerd-rootless.sh
 +
}
 +
 
 +
# Função para exportar variáveis de ambiente para executar comandos do docker rootless
 +
function docker-rootless-export(){
 +
  MYUSER=$(whoami)
 +
  echo -e "Exporting Environment Variables for Docker Rootless Daemon..."
 +
  export USER_DOCKER_DIR=$USER_DOCKER_BASE_DIR/${MYUSER}/docker-rootless
 +
  # Verifica se o diretório do usuário existe e pode ser escrita pelo docker rootless
 +
  if [ -d "$USER_DOCKER_DIR" ] && [ -w "$USER_DOCKER_DIR" ]; then
 +
    export DOCKER_HOST=unix://$USER_DOCKER_DIR/.docker/run/docker.sock
 +
    echo -e "  USER_DOCKER_DIR=$USER_DOCKER_DIR\n  DOCKER_HOST=$DOCKER_HOST"
 +
  else
 +
    echo -e "ERROR!\n  USER_DOCKER_DIR=$USER_DOCKER_DIR does not exist or is not writable!"
 +
    echo -e "  Please run docker-rootless-create-dir first!"
 +
    unset USER_DOCKER_DIR
 +
    return 1
 +
  fi
 +
}
 +
</pre>
 +
|}
 +
 
 +
=== Utilização ===
 +
Uma vez que tiver as funções salvas em seu <code>'''~/.bashrc'''</code> elas serão usadas para:
 +
 
 +
{| class="wikitable"
 +
|+ Como usar as funções docker-rootless-*
 +
|-
 +
! Função !! Descrição !! Utilização
 +
|-
 +
|''docker-rootless-create-dir()''<br><br>
 +
|Cria uma pasta para os arquivos do docker rootless daemon em <code>"/draft-hdd/<usuario>/docker-rootless"</code>
 +
|Usada apenas a primeira vez na máquina. Se a pasta já foi criada anteriormente, não precisa mais usar essa função na mesma máquina.
 +
|-
 +
|''docker-rootless-daemon-run()''<br><br>
 +
|Executar o docker rootless daemon no terminal atual no tmux ou byobu
 +
|Usada uma vez, para não haver outro terminal executando o docker rootless daemon na máquina.
 +
|-
 +
|''docker-rootless-export()''<br><br>
 +
|Exportar as variáveis de ambiente com o path correto do docker rootless daemon e do docker.sock (''XDG_RUNTIME_DIR'' e ''DOCKER_HOST'')
 +
|Usada em todo novo terminal que abrir e quiser usar comando docker. Também pode ser colocada no final do ~/.bashrc para valer automaticamente.
 +
|}
 +
 
 +
 
 +
Para utilizar o docker:
 +
 
 +
# Faça ''ssh'' numa das máquinas que tem o docker rootless instalado
 +
# Se a pasta <code>"/draft-hdd/<usuario>/docker-rootless"</code> ainda não foi criada para seu usuário na máquina, execute: <code>'''docker-rootless-create-dir'''</code>
 +
# No terminal abra o multiplexador de terminais, por exemplo, comando: <code>'''tmux'''</code>
 +
# Dentro da '''janela 0''' do tmux, execute o docker rootless daemon: <code>'''docker-rootless-daemon-run'''</code>
 +
# Abra outra janela no tmux: ctrl+b c
 +
# Na '''janela 1''' faça o export do path para executar comandos docker:  <code>'''docker-rootless-export'''</code>
 +
# Na '''janela 1''' execute os comandos docker:  <code>'''docker version ; docker compose version; docker info;'''</code>
 +
# Na '''janela 1''' download e execute uma imagem de teste (13kB):  <code>'''docker run hello-world'''</code>
 +
 
 +
<br><br><br>
 +
 
 +
=== Testando Docker Rootless ===
 +
Considerando que a pasta para seu usuário na máquina já foi criada, ou seja, já existe o caminho <code>"/draft-hdd/<usuario>/docker-rootless"</code>. Caso ainda não exista, execute: <code>'''docker-rootless-create-dir'''</code>
 +
<br><br>
 +
# Faça ''ssh'' numa das máquinas que tem o docker rootless instalado
 +
# No terminal abra o multiplexador de terminais, por exemplo, comando: <code>'''tmux'''</code>
 +
# Dentro da '''janela 0''' do tmux, execute o docker rootless daemon: <code>'''docker-rootless-daemon-run'''</code>
 +
# Abra outra janela no tmux: ctrl+b c
 +
# Na '''janela 1''' faça o export do path para executar comandos docker:  <code>'''docker-rootless-export'''</code>
 +
# Na '''janela 1''' download e execute uma das imagens de teste abaixo: 
 +
<span style="color: red;">Atenção para escolher uma imagem com CUDA compatível com o driver de vídeo Nvidia instalado na máquina!</span><br>Para saber a versão de CUDA toolkit suportada pelo driver Nvidia utilize o comando <code>'''nvidia-smi'''</code>
 +
<br><br>
 +
{| class="wikitable" style="font-weight:bold; font-family:serif !important;"
 +
|- style="font-weight:normal; text-align:center;"
 +
! Comando docker
 +
! image size
 +
|-
 +
| style="background-color:#CCC;" | docker run hello-world
 +
| style="font-weight:normal;" | 13kB
 +
|-
 +
| style="background-color:#CCC;" | docker run --gpus all nvidia/cuda:11.2.2-base-ubuntu20.04 nvidia-smi
 +
| style="font-weight:normal;" | 125MB
 +
|-
 +
| style="background-color:#CCC;" | docker run --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
 +
| style="font-weight:normal;" | 154MB
 +
|-
 +
| style="background-color:#CCC;" | docker run --gpus all nvidia/cuda:12.0.0-base-ubuntu20.04 nvidia-smi
 +
| style="font-weight:normal;" | 240MB
 +
|-
 +
| style="background-color:#CCC;" | docker run --gpus all nvidia/cuda:12.2.2-base-ubuntu20.04 nvidia-smi
 +
| style="font-weight:normal;" | 242MB
 +
|-
 +
| style="background-color:#CCC;" | docker run --gpus all nvidia/cuda:12.2.2-base-ubuntu22.04 nvidia-smi
 +
| style="font-weight:normal;" | 239MB
 +
|}
 +
<br><br><br>
 +
 
 +
== Limpar dados do docker rootless: cache, images e containers ==
 +
 
 +
Para desocupar espaço em disco das máquinas, caso não esteja utilizando o docker, mas deseja manter a estrutura de pastas do docker rootless daemon, pode-se apagar todas as imagens, cache e containers com:
 +
 
 +
<code>'''docker system prune --all'''</code>
 +
 
 +
 
 +
 
 +
Alguns links de referencia:
 +
* https://stackoverflow.com/questions/44785585/how-can-i-delete-all-local-docker-images
 +
* https://contabo.com/blog/how-to-remove-docker-volumes-images-and-containers/?gad_source=1&gclid=CjwKCAjwydSzBhBOEiwAj0XN4JA5Mz8X1bAK-PaXKPz9PyQnJKdahvYG3Z6CBm5ydgRmsNymOFU9FhoC4a0QAvD_BwE
 +
* https://earthly.dev/blog/docker-image-storage-on-host/
 +
* https://docs.docker.com/reference/cli/docker/system/prune/#extended-description
 +
 
 +
 
 +
== Docker abrindo janela no Ubuntu ==
 +
exemplo com ROS<br>
 +
 
 +
 
 +
<pre>
 +
docker run --detach --privileged \
 +
--volume /tmp/.X11-unix:/tmp/.X11-unix \
 +
--volume /home:/home/host \
 +
--device=/dev/bus/usb:/dev/bus/usb \
 +
--volume /dev:/dev \
 +
--runtime=nvidia \
 +
--gpus 'all,"capabilities=utility,display,compute"' \
 +
--env DISPLAY=$DISPLAY \
 +
--network=host \
 +
--name ros_noetic_gps_testing_container \
 +
ros_noetic_gps_testing:latest \
 +
tail -f /dev/null
 +
</pre>
 +
 
 +
 
 +
<pre>
 +
#docker run -it -v "$PWD":/ros2_ws/ -P --device=/dev/ttyACM0 --device=/dev/bus/usb:/dev/bus/usb --name ros2_dev ros2_ws
 +
 
 +
#docker exec -it ros2_dev /bin/bash
 +
 
 +
docker run -it \
 +
--name ros2_work \
 +
--privileged \
 +
--env DISPLAY=$DISPLAY \
 +
--volume /tmp/.X11-unix:/tmp/.X11-unix \
 +
--volume "$PWD":/ros2_ws/ \
 +
--device=/dev/ttyACM0 \
 +
--device=/dev/ttyACM1 \
 +
--device=/dev/bus/usb:/dev/bus/usb \
 +
--gpus 'all,"capabilities=utility,display,compute"' \
 +
--runtime=nvidia \
 +
--network=host \
 +
ros2_dev \
 +
bash
 +
</pre>
 +
 
 +
== Criar regra udev para dispositivo USB ==
 +
Para descobrir o idProduct e idVendor do dispositivo, pode-se usar:
 +
 
 +
<code> udevadm info -a -n /dev/ttyACM0 </code>
 +
 
 +
 
 +
Para criar o arquivo com a regra:
 +
 
 +
<code> sudo nano /etc/udev/rules.d/99-ublox-gps.rules </code>
 +
 
 +
Adicionar essa linha no arquivo e salvar o arquivo:
 +
 
 +
<code>
 +
SUBSYSTEM=="tty", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", MODE="0666", GROUP="dialout"
 +
 
 +
</code>
 +
 
 +
Se quiser criar um novo nome (link simbolico /dev/ublox) adicionar SYMLINK:
 +
 
 +
<code>SUBSYSTEM=="tty", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", SYMLINK+="ublox", MODE="0666", GROUP="dialout"
 +
</code>
 +
 
 +
 
 +
Desconectar e conectar o dispositivo da USB novamente para acionar a nova regra
 +
 
 +
<br><br><br>
 +
 
 +
== Criar docker com S.O. windows ou macOs com acesso por site web ==
 +
 
 +
* https://github.com/dockur/windows
 +
 
 +
* https://github.com/dockur/macos
 +
 
 +
<br><br>
 +
Exemplo de docker compose com win11, 2 Cores, HD 64GB, RAM 8GB
 +
 
 +
{| class="wikitable"
 +
|-
 +
! <code>compose.yaml</code>
 +
|-
 +
|
 +
<pre>
 +
services:
 +
  windows:
 +
    image: dockurr/windows
 +
    container_name: windows
 +
    environment:
 +
      VERSION: "11"
 +
      DISK_SIZE: "64"
 +
      RAM_SIZE: "8"
 +
      CPU_CORES: "2"
 +
    devices:
 +
      - /dev/kvm
 +
      - /dev/net/tun
 +
    cap_add:
 +
      - NET_ADMIN
 +
    ports:
 +
      - 8006:8006
 +
      - 3389:3389/tcp
 +
      - 3389:3389/udp
 +
    volumes:
 +
      - ./windows:/storage
 +
    restart: always
 +
    stop_grace_period: 2m
 +
</pre>
 +
|}
 +
 
 +
Para acessar a tela do Win11 entre a URL no navegador <code>localhost:8006</code>
 +
<br><br><br>
 +
 
 +
 
 +
== Exemplo de Dockerfile usado no Jetracer ==
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Modelo de Dockerfile usado no Jetracer
 +
|-
 +
 +
<pre>
 +
# Usa a imagem base do Ubuntu 20.04 para arquitetura ARM64 (Jetson Nano)
 +
FROM arm64v8/ubuntu:20.04
 +
 
 +
# Evita prompts interativos durante a instalação de pacotes
 +
ENV DEBIAN_FRONTEND=noninteractive
 +
 
 +
# Atualiza o sistema e instala ferramentas básicas
 +
RUN apt-get update && apt-get install -y \
 +
curl \                # Utilitário para baixar arquivos via HTTP
 +
    gnupg2 \              # Para importar chaves GPG
 +
    lsb-release \        # Para detectar a versão do Ubuntu
 +
    locales \            # Para configurar o sistema com suporte a UTF-8
 +
    sudo \                # Permite uso do comando sudo
 +
    && locale-gen en_US en_US.UTF-8 \            # Gera locale UTF-8
 +
    && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8  # Atualiza variáveis de locale
 +
 
 +
# Define variáveis de ambiente para o locale em UTF-8
 +
ENV LANG=en_US.UTF-8 \
 +
    LC_ALL=en_US.UTF-8
 +
 
 +
# Adiciona o repositório do ROS oficial e sua chave GPG
 +
RUN curl -sSL "http://packages.ros.org/ros.key" | apt-key add - && \
 +
    echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list
 +
 
 +
# Instala o ROS Noetic (ros-base) e ferramentas auxiliares
 +
RUN apt-get update && apt-get install -y \
 +
    ros-noetic-ros-base \              # ROS básico, sem GUI (leve)
 +
    python3-rosdep \                    # Gerenciador de dependências ROS
 +
    python3-rosinstall \              # Para importar pacotes ROS
 +
    python3-rosinstall-generator \    # Ferramenta para gerar dependências
 +
    python3-wstool \                  # Gerenciador de workspaces
 +
    python3-pip \                      # Gerenciador de pacotes Python
 +
    && rm -rf /var/lib/apt/lists/*    # Remove cache para reduzir tamanho da imagem
 +
 
 +
# Inicializa o rosdep (necessário para instalar dependências de pacotes ROS)
 +
RUN rosdep init && rosdep update
 +
 
 +
# Adiciona o script de configuração do ROS no bashrc do root
 +
RUN echo "source /opt/ros/noetic/setup.bash" >> /root/.bashrc
 +
 
 +
# Define o shell padrão como bash (necessário para scripts do ROS funcionarem corretamente)
 +
SHELL ["/bin/bash", "-c"]
 +
 
 +
# Define uma variável de ambiente com a distro do ROS
 +
ENV ROS_DISTRO=noetic
 +
 
 +
# Cria o diretório do workspace ROS (catkin workspace)
 +
RUN mkdir -p /root/catkin_ws/src
 +
 
 +
# Define o diretório de trabalho padrão para o contêiner
 +
WORKDIR /root/catkin_ws
 +
 
 +
# Comando padrão ao iniciar o contêiner: inicia um terminal bash
 +
CMD ["bash"]
 +
 
 +
</pre>
 +
|}
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Comando para o docker build
 +
|-
 +
 +
<pre>
 +
docker build -t ros-noetic-nano .
 +
</pre>
 +
|}
  
Com isso, a configuração está pronta. Confirme que o Docker está funciona com <code>docker run hello-world</code> ou <code>docker version</code>.
+
{| class="wikitable"
 +
|-
 +
! Comando de RUN, primeira vez
 +
|-
 +
 +
<pre>
 +
docker run -it --name meu_ros_container \-v ~/jetrace/container:/root/catkin_ws \
 +
  ros-noetic-nano
 +
</pre>
 +
|}
  
==Problemas com a instalação na máquina==
 
Caso mesmo após estes passos o docker apresente problemas, pode ser necessário realizar a configuração de modo a executar ele manualmente direcionado para a sua pasta na /homeLocal. Para isso é preciso é preciso:
 
# Criar uma pasta na /homeLocal do usuário que será usada pelo runtime do dockerd-rootless, executando:<br>
 
<code>mkdir /homeLocal/<user>/.docker</code><br>
 
<code>mkdir /homeLocal/<user>/.docker/run</code>
 
#Após isso é preciso criar as variaveis de ambiente no ~/.bashrc para XDG_RUNTIME_DIR e DOCKER_HOST.
 
<code>export XDG_RUNTIME_DIR=/homeLocal/<user>/.docker/run</code>
 
<code>export DOCKER_HOST=unix:///homeLocal/<user>/.docker/run/docker.sock</code>
 
  
A partir deste ponto, enquanto quiser executar o docker, é preciso deixar uma janela excutando o bash script <code>dockerd-rootless.sh</code>. Para isso abra uma janela do tmux ou byobu, e execute:
+
{| class="wikitable"
<code>bash dockerd-rootless.sh</code>
+
|-
 +
! Comando START
 +
|-
 +
 +
<pre>
 +
docker start -ai develop_container
 +
</pre>
 +
|}
  
Em outro terminal, é possível verificar a instalação executando <code>docker run hello-world</code> ou <code>docker version</code>.
+
== Dicas Docker Compose ==
 +
* https://docs.docker.com/compose/gettingstarted/
 +
<br><br><br>

Latest revision as of 14:28, 25 July 2025

Docker Rootless Mode

O modo disponível do Docker para os usuários da rede é o Docker Engine no modo Rootless, ou seja, apenas a versão em linha de comando e no modo de acesso non-root.

Em geral, funciona para todas as aplicações e pode-se ler mais informações no link Docker Rootless

Importante: para estas configurações é necessário que a máquina tenha um docker instalado com versão >= 20.10 (pode ser conferido com: docker version)

Este processo ainda se encontra em uma fase experimental e não está disponível em todas as máquinas. As máquinas disponíveis com docker até o momento são PROC1, PROC2, PROC5, PROC6, PROC7, EPONA, NYMERIA, DROGON, EVA, WALL-E, MAGRITTE e DALEK.


Modo 1(systemd): Configuração Docker rootless com Systemd (não é possível usar simultaneamente em outras máquinas, apenas em uma máquina da rede por vez)



A opção mais intuitiva para executar o Docker Rootless é gerenciando pelo systemctl --user. Porém tem a limitação de funcionar em apenas uma máquina da rede por vez, pois o arquivo que gerencia o systemctl do usuário é salvo na /home que é compartilhada em todas as máquinas, portanto apenas um processo docker rootless do usuário pode ser criado, mas em qualquer máquina da rede.

Pré-requisitos

Para utilizar docker rootless em uma máquina no laboratório é preciso que o usuário:

  • solicite à equipe de rede para criar uma pasta de rascunho no disco local como /draft-xxx/nome_do_usuario e dar permissão de leitura/escrita.
  • solicite à equipe de rede a instalação do docker na máquina.



Configuração

Feito estas etapas, para configurar o acesso na máquina é preciso seguir os seguintes passos para executar o docker rootless:

  1. Crie a pasta ~/.config/docker com o comando mkdir -p ~/.config/docker.
  2. Altere a pasta de armazenamento dos arquivos de cache do Docker para a pasta de rascunho /draft-xxx com:

echo '{"data-root":"/<path-em-disco-local>/<user>/docker-cache"}' | tee ~/.config/docker/daemon.json

Importante: Lembre-se de ajustar o <path-em-disco-local>/<user> para uma armazenamento de rascunho na máquina e alguma pasta do seu usuário (por exemplo, /draft-hdd/fulano).

Esses dois primeiros passos são específicos para as máquinas do VeRLab: por padrão o Docker guarda arquivos na /home do usuário, mas essa pasta é compartilhada em rede (por NFS ou MooseFS) e o Docker não dá suporte a isso.Aqui está um issue citando o problema

  1. Execute dockerd-rootless-setuptool.sh install.



Importante: Após terminar, o comando vai pedir que você altere seu .bashrc para adicionar uma linha semelhante a export DOCKER_HOST=unix:///run/user/<uid>/docker.sock (varia por usuário). Faça essa alteração antes de prosseguir copiando e colando o comando no terminal.

  1. Reinicie o Bash com exec bash.
  2. Ative a inicialização automática do Docker em seu usuário: systemctl --user enable --now docker ou manualmente: systemctl --user start docker


Com isso, a configuração está pronta!

Utilização

Comandos para confirmar se o Docker está funcionando:

  • Verificar status do docker daemon: systemctl --user status docker.service
  • Parar docker daemon: systemctl --user stop docker.service
  • Verificar configurações do Docker Rootless: docker version ou docker info
  • Baixar uma imagem teste e executá-la: docker run hello-world




Modo 2 (Manual): Configuração Docker Rootless "Manual" para execução simultânea em várias máquinas da rede



Essa opção pode parecer menos intuitiva, pois o usuário precisará executar manualmente o daemon do docker rootless em um terminal e mantê-lo em execução para poder utilizar os comandos docker em outros terminais.

Isso pode ser facilmente feito utilizando os multiplexadores de terminal como tmux ou byobu.

Uma vez que parar a execução do docker daemon com ctrl+c ou fechar o terminal, isso vai "matar" a execução do docker rootless na máquina e parar todos seus containers de forma abrupta. Porém tem a flexibilidade de não precisar da pasta /home para armazenar as configurações do daemon, então com essa configuração é possível executar o docker rootless em várias máquinas simultaneamente!

Pré-requisitos

Para utilizar Docker Rootless em uma máquina no laboratório é preciso que o usuário:

  • solicite à equipe de rede para criar uma pasta de rascunho no disco local como /draft-xxx/nome_do_usuario e dar permissão de leitura/escrita.
  • solicite à equipe de rede a instalação do docker na máquina.


Configuração

  1. Abra seu arquivo ~/.bashrc no editor de texto preferido, se for no terminal pode usar o nano: nano ~/.bashrc
  2. Cole as seguintes funções no final desse arquivo e salve o mesmo:
Adicionar funções no .bashrc para facilitar o uso do docker-rootless mode
# Funções para adicionar no final do arquivo ~/.bashrc e usar docker rootless na rede VeRLab/JLab
# v4 mai/2025 by mauferrari

# Path para o diretório base a ser utilizado pelo docker rootless do usuário
export USER_DOCKER_BASE_DIR=/draft-hdd

# Função para criar pastas e configuração do docker rootless
function docker-rootless-create-dir(){
  MYUSER=$(whoami)
  # Cria environment variables para pastas
  echo -e "Creating Docker Rootless Folder for user $MYUSER..."
  export USER_BASE_DIR=$USER_DOCKER_BASE_DIR/${MYUSER}
  export USER_DOCKER_DIR=$USER_BASE_DIR/docker-rootless
  echo -e "  USER_BASE_DIR=$USER_BASE_DIR\n  USER_DOCKER_DIR=$USER_DOCKER_DIR"
  # Verfica se o diretorio base do usuário existe
  if [ ! -d "$USER_BASE_DIR" ]; then
    echo -e "ERROR!\n  USER_BASE_DIR=$USER_BASE_DIR needs to be created by user '$MYUSER'!"
    unset USER_BASE_DIR
    unset USER_DOCKER_DIR
    return 1
  fi

  # Verifica pasta do usuário usada pelo docker rootless
  if [ ! -w "$USER_BASE_DIR" ]; then
    echo -e "ERROR!\n  USER_BASE_DIR=$USER_BASE_DIR needs to be writable by user '$MYUSER'!"
    unset USER_BASE_DIR
    unset USER_DOCKER_DIR
    return 2
  fi
  # Verifica se a pasta do usuário já existe
  if [ -d "$USER_DOCKER_DIR" ]; then
    echo -e "ERROR!\n  USER_DOCKER_DIR=$USER_DOCKER_DIR already exists!"
    echo -e "  Please remove it or use another folder!"
    unset USER_BASE_DIR
    unset USER_DOCKER_DIR
    return 3
  fi
  # Cria pastas usadas pelo docker rootless
  mkdir --parents $USER_DOCKER_DIR
  export XDG_RUNTIME_DIR=$USER_DOCKER_DIR/.docker/run
  export XDG_CONFIG_HOME=$USER_DOCKER_DIR/.config
  mkdir --parents $XDG_RUNTIME_DIR
  mkdir --parents $XDG_CONFIG_HOME/docker

  # Cria configuração do docker rootless
  echo "{\"data-root\":\"${USER_DOCKER_DIR}/docker-cache\"}" | tee $XDG_CONFIG_HOME/docker/daemon.json  && \
  nvidia-ctk runtime configure --runtime=docker --config=$XDG_CONFIG_HOME/docker/daemon.json

  echo -e "\n\n  HOME=$HOME \n  XDG_CONFIG_HOME=$XDG_CONFIG_HOME \n  XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \n  XDG_DATA_HOME=$XDG_DATA_HOME \n  DOCKER_HOST=$DOCKER_HOST"
  echo -e "\n\ncat $XDG_CONFIG_HOME/docker/daemon.json\n" && cat $XDG_CONFIG_HOME/docker/daemon.json
  echo -e "\n\nDocker Rootless Folders and Config Files Successfully Created!"
}

# Função para iniciar manualmente daemon do docker no modo rootless
function docker-rootless-daemon-run(){
  MYUSER=$(whoami)
  echo -e "Exporting Environment Variables for Docker Rootless Daemon..."
  export USER_DOCKER_DIR=$USER_DOCKER_BASE_DIR/${MYUSER}/docker-rootless

  echo -e "  USER_DOCKER_DIR=$USER_DOCKER_DIR\n  XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR\n  XDG_CONFIG_HOME=$XDG_CONFIG_HOME"
  # Verifica se o diretório do usuário existe e pode ser escrita pelo docker rootless
  if [ ! -d "$USER_DOCKER_DIR" ] && [ ! -w "$USER_DOCKER_DIR" ]; then
    echo -e "ERROR!\n  USER_DOCKER_DIR=$USER_DOCKER_DIR does not exist or is not writable!"
    echo -e "  Please run docker-rootless-create-dir first!"
    unset USER_DOCKER_DIR
    return 1
  fi
  export XDG_RUNTIME_DIR=$USER_DOCKER_DIR/.docker/run
  export XDG_CONFIG_HOME=$USER_DOCKER_DIR/.config
  # Verifica se o daemon do docker rootless está rodando
  echo -e "Checking Docker Rootless Daemon..."
  if [ -S $XDG_RUNTIME_DIR/docker.sock ]; then
    echo -e "ERROR!\n  Docker Rootless Daemon is already running at $XDG_RUNTIME_DIR!"
    echo -e "  Please stop it first!"
    unset USER_DOCKER_DIR
    unset XDG_RUNTIME_DIR
    unset XDG_CONFIG_HOME
    return 2
  fi
  # Start docker daemon
  echo -e "\n\n  HOME=$HOME \n  XDG_CONFIG_HOME=$XDG_CONFIG_HOME \n  XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \n  XDG_DATA_HOME=$XDG_DATA_HOME \n  DOCKER_HOST=$DOCKER_HOST"
  echo -e "\n\ncat $XDG_CONFIG_HOME/docker/daemon.json\n" && cat $XDG_CONFIG_HOME/docker/daemon.json
  echo -e "Starting Docker Rootless Daemon..."
  dockerd-rootless.sh
}

# Função para exportar variáveis de ambiente para executar comandos do docker rootless
function docker-rootless-export(){
  MYUSER=$(whoami)
  echo -e "Exporting Environment Variables for Docker Rootless Daemon..."
  export USER_DOCKER_DIR=$USER_DOCKER_BASE_DIR/${MYUSER}/docker-rootless
  # Verifica se o diretório do usuário existe e pode ser escrita pelo docker rootless
  if [ -d "$USER_DOCKER_DIR" ] && [ -w "$USER_DOCKER_DIR" ]; then
    export DOCKER_HOST=unix://$USER_DOCKER_DIR/.docker/run/docker.sock
    echo -e "  USER_DOCKER_DIR=$USER_DOCKER_DIR\n  DOCKER_HOST=$DOCKER_HOST"
  else
    echo -e "ERROR!\n  USER_DOCKER_DIR=$USER_DOCKER_DIR does not exist or is not writable!"
    echo -e "  Please run docker-rootless-create-dir first!"
    unset USER_DOCKER_DIR
    return 1
  fi
}

Utilização

Uma vez que tiver as funções salvas em seu ~/.bashrc elas serão usadas para:

Como usar as funções docker-rootless-*
Função Descrição Utilização
docker-rootless-create-dir()

Cria uma pasta para os arquivos do docker rootless daemon em "/draft-hdd/<usuario>/docker-rootless" Usada apenas a primeira vez na máquina. Se a pasta já foi criada anteriormente, não precisa mais usar essa função na mesma máquina.
docker-rootless-daemon-run()

Executar o docker rootless daemon no terminal atual no tmux ou byobu Usada uma vez, para não haver outro terminal executando o docker rootless daemon na máquina.
docker-rootless-export()

Exportar as variáveis de ambiente com o path correto do docker rootless daemon e do docker.sock (XDG_RUNTIME_DIR e DOCKER_HOST) Usada em todo novo terminal que abrir e quiser usar comando docker. Também pode ser colocada no final do ~/.bashrc para valer automaticamente.


Para utilizar o docker:

  1. Faça ssh numa das máquinas que tem o docker rootless instalado
  2. Se a pasta "/draft-hdd/<usuario>/docker-rootless" ainda não foi criada para seu usuário na máquina, execute: docker-rootless-create-dir
  3. No terminal abra o multiplexador de terminais, por exemplo, comando: tmux
  4. Dentro da janela 0 do tmux, execute o docker rootless daemon: docker-rootless-daemon-run
  5. Abra outra janela no tmux: ctrl+b c
  6. Na janela 1 faça o export do path para executar comandos docker: docker-rootless-export
  7. Na janela 1 execute os comandos docker: docker version ; docker compose version; docker info;
  8. Na janela 1 download e execute uma imagem de teste (13kB): docker run hello-world




Testando Docker Rootless

Considerando que a pasta para seu usuário na máquina já foi criada, ou seja, já existe o caminho "/draft-hdd/<usuario>/docker-rootless". Caso ainda não exista, execute: docker-rootless-create-dir

  1. Faça ssh numa das máquinas que tem o docker rootless instalado
  2. No terminal abra o multiplexador de terminais, por exemplo, comando: tmux
  3. Dentro da janela 0 do tmux, execute o docker rootless daemon: docker-rootless-daemon-run
  4. Abra outra janela no tmux: ctrl+b c
  5. Na janela 1 faça o export do path para executar comandos docker: docker-rootless-export
  6. Na janela 1 download e execute uma das imagens de teste abaixo:

Atenção para escolher uma imagem com CUDA compatível com o driver de vídeo Nvidia instalado na máquina!
Para saber a versão de CUDA toolkit suportada pelo driver Nvidia utilize o comando nvidia-smi

Comando docker image size
docker run hello-world 13kB
docker run --gpus all nvidia/cuda:11.2.2-base-ubuntu20.04 nvidia-smi 125MB
docker run --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi 154MB
docker run --gpus all nvidia/cuda:12.0.0-base-ubuntu20.04 nvidia-smi 240MB
docker run --gpus all nvidia/cuda:12.2.2-base-ubuntu20.04 nvidia-smi 242MB
docker run --gpus all nvidia/cuda:12.2.2-base-ubuntu22.04 nvidia-smi 239MB




Limpar dados do docker rootless: cache, images e containers

Para desocupar espaço em disco das máquinas, caso não esteja utilizando o docker, mas deseja manter a estrutura de pastas do docker rootless daemon, pode-se apagar todas as imagens, cache e containers com:

docker system prune --all


Alguns links de referencia:


Docker abrindo janela no Ubuntu

exemplo com ROS


docker run --detach --privileged \ 
--volume /tmp/.X11-unix:/tmp/.X11-unix \ 
--volume /home:/home/host \ 
--device=/dev/bus/usb:/dev/bus/usb \ 
--volume /dev:/dev \ 
--runtime=nvidia \ 
--gpus 'all,"capabilities=utility,display,compute"' \ 
--env DISPLAY=$DISPLAY \ 
--network=host \ 
--name ros_noetic_gps_testing_container \ 
ros_noetic_gps_testing:latest \ 
tail -f /dev/null


#docker run -it -v "$PWD":/ros2_ws/ -P --device=/dev/ttyACM0 --device=/dev/bus/usb:/dev/bus/usb --name ros2_dev ros2_ws

#docker exec -it ros2_dev /bin/bash

docker run -it \
--name ros2_work \
--privileged \
--env DISPLAY=$DISPLAY \
--volume /tmp/.X11-unix:/tmp/.X11-unix \
--volume "$PWD":/ros2_ws/ \
--device=/dev/ttyACM0 \
--device=/dev/ttyACM1 \
--device=/dev/bus/usb:/dev/bus/usb \
--gpus 'all,"capabilities=utility,display,compute"' \
--runtime=nvidia \
--network=host \
ros2_dev \
bash

Criar regra udev para dispositivo USB

Para descobrir o idProduct e idVendor do dispositivo, pode-se usar:

udevadm info -a -n /dev/ttyACM0


Para criar o arquivo com a regra:

sudo nano /etc/udev/rules.d/99-ublox-gps.rules

Adicionar essa linha no arquivo e salvar o arquivo:

SUBSYSTEM=="tty", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", MODE="0666", GROUP="dialout"

Se quiser criar um novo nome (link simbolico /dev/ublox) adicionar SYMLINK:

SUBSYSTEM=="tty", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", SYMLINK+="ublox", MODE="0666", GROUP="dialout"


Desconectar e conectar o dispositivo da USB novamente para acionar a nova regra




Criar docker com S.O. windows ou macOs com acesso por site web



Exemplo de docker compose com win11, 2 Cores, HD 64GB, RAM 8GB

compose.yaml
services:
  windows:
    image: dockurr/windows
    container_name: windows
    environment:
      VERSION: "11"
      DISK_SIZE: "64"
      RAM_SIZE: "8"
      CPU_CORES: "2"
    devices:
      - /dev/kvm
      - /dev/net/tun
    cap_add:
      - NET_ADMIN
    ports:
      - 8006:8006
      - 3389:3389/tcp
      - 3389:3389/udp
    volumes:
      - ./windows:/storage
    restart: always
    stop_grace_period: 2m

Para acessar a tela do Win11 entre a URL no navegador localhost:8006



Exemplo de Dockerfile usado no Jetracer

Modelo de Dockerfile usado no Jetracer
# Usa a imagem base do Ubuntu 20.04 para arquitetura ARM64 (Jetson Nano)
FROM arm64v8/ubuntu:20.04

# Evita prompts interativos durante a instalação de pacotes
ENV DEBIAN_FRONTEND=noninteractive

# Atualiza o sistema e instala ferramentas básicas
RUN apt-get update && apt-get install -y \
		curl \                # Utilitário para baixar arquivos via HTTP
    gnupg2 \              # Para importar chaves GPG
    lsb-release \         # Para detectar a versão do Ubuntu
    locales \             # Para configurar o sistema com suporte a UTF-8
    sudo \                # Permite uso do comando sudo
    && locale-gen en_US en_US.UTF-8 \             # Gera locale UTF-8
    && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8  # Atualiza variáveis de locale

# Define variáveis de ambiente para o locale em UTF-8
ENV LANG=en_US.UTF-8 \
    LC_ALL=en_US.UTF-8

# Adiciona o repositório do ROS oficial e sua chave GPG
RUN curl -sSL "http://packages.ros.org/ros.key" | apt-key add - && \
    echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list

# Instala o ROS Noetic (ros-base) e ferramentas auxiliares
RUN apt-get update && apt-get install -y \
    ros-noetic-ros-base \               # ROS básico, sem GUI (leve)
    python3-rosdep \                    # Gerenciador de dependências ROS
    python3-rosinstall \               # Para importar pacotes ROS
    python3-rosinstall-generator \     # Ferramenta para gerar dependências
    python3-wstool \                   # Gerenciador de workspaces
    python3-pip \                      # Gerenciador de pacotes Python
    && rm -rf /var/lib/apt/lists/*     # Remove cache para reduzir tamanho da imagem

# Inicializa o rosdep (necessário para instalar dependências de pacotes ROS)
RUN rosdep init && rosdep update

# Adiciona o script de configuração do ROS no bashrc do root
RUN echo "source /opt/ros/noetic/setup.bash" >> /root/.bashrc

# Define o shell padrão como bash (necessário para scripts do ROS funcionarem corretamente)
SHELL ["/bin/bash", "-c"]

# Define uma variável de ambiente com a distro do ROS
ENV ROS_DISTRO=noetic

# Cria o diretório do workspace ROS (catkin workspace)
RUN mkdir -p /root/catkin_ws/src

# Define o diretório de trabalho padrão para o contêiner
WORKDIR /root/catkin_ws

# Comando padrão ao iniciar o contêiner: inicia um terminal bash
CMD ["bash"]

Comando para o docker build
docker build -t ros-noetic-nano .
Comando de RUN, primeira vez
docker run -it --name meu_ros_container \-v ~/jetrace/container:/root/catkin_ws \
  ros-noetic-nano


Comando START
docker start -ai develop_container

Dicas Docker Compose