DEV Community

Cover image for Histórico do Bash dentro de Contêineres Docker
Lucas Perez
Lucas Perez

Posted on

Histórico do Bash dentro de Contêineres Docker

🏴󠁧󠁢󠁥󠁮󠁧󠁿 English version of this text here!

Não sei vocês, mas eu adoro ter um ambiente de desenvolvimento dockerizado. Não ter que me preocupar com versionamento e dependências quando for pulando de projeto em projeto é muito bom.

Mas algo que eu não gosto tanto assim é quando eu saio do contêiner e mais tarde volto nele e descubro que perdi o histórico de todos os comandos anteriores, então não posso buscar mais nada nem com ctrl+R nem com seta pra cima/ctrl+P. Imagens de dor e sofrimento!

Decidi então tentar manter esse histórico, e para fazer isso, primeiro eu pensei, como que o bash faz pra saber os comandos anteriores?

No fim parece que há uma variável de ambiente chamada HISTFILE que contém o caminho para um arquivo de texto com o histórico de comandos do bash. Aparentemente, por padrão ela é configurada para $HOME/.bash_history.

OBS: Se o teu contêiner rodar outro shell diferente do bash, teríamos que descobrir onde que esse outro shell guarda o seu histórico.

Então uma solução que encontrei foi de mudar essa variável de ambiente pra algum outro lugar, algum lugar dentro do diretório do projeto que estou trabalhando pra evitar perdê-lo depois de parar o contêiner.

Vamos supor que a imagem do docker cria um diretório /app com todo o conteúdo do projeto dentro, eu poderia definir HISTFILE como sendo /app/.bash_history, e daí se mapearmos tudo com um volume, vamos ter um histórico persistente entre sessões do docker. O nome do arquivo em si nem precisa ser .bash_history, poderia ser algo como /app/.docker_bash_history, por exemplo.

Pra começar um contêiner com uma variável específica, podemos passar a opção -e:

docker exec -it -e HISTFILE=/app/.bash_history -v <volume> <...outras coisas...>
Enter fullscreen mode Exit fullscreen mode

Se estivermos usando o Docker Compose, podemos ou passar um "env file" (um arquivo com variáveis de ambiente) ou as variáveis diretamente no docker-compose.yml (ou qualquer outro arquivo de configuração que estejas usando):

# arquivo de configuração de exemplo

services:
  app:
    build: .
    volumes:
      - .:/app # mapeando este volume para persistir as modificações no nosso novo arquivo de histórico
    command: echo Oi!
    env_file: # podemos definir as variáveis dentro deste arquivo .env
      - .env
    environment: # ou então podemos passá-las diretamente aqui
      HISTFILE: /app/.bash_history
Enter fullscreen mode Exit fullscreen mode

Um problema surge com essa solução, entretanto. Agora eu tenho um arquivo novo na raiz do meu projeto, um arquivo que o git vai ver, a menos que eu o coloque no nosso .gitignore, coisa que eu realmente acho que devíamos. Eu não quero commitar meu histórico e nem quero puxar o histórico de outras pessoas, até porque isso acabaria com o propósito de ter um arquivo de histórico. Além disso, acabei de criar um novo arquivo na raiz, que pode ficar poluindo o diretório base do projeto. Talvez aches um outro lugar melhor para esses arquivos.

E isso é praticamente tudo! Eu não sei o quão ruim ou boa é essa ideia, mas estou gostando até aqui. Eu criei um diretorio novo na raiz do projeto, dotfiles/, que tem também outros arquivos parecidos, como .irb_history e .irbrc em um projeto ruby. Pra conseguir ter isso tudo funcionando, eu tive que adicionar as seguintes linhas ao arquivo dotfiles/.irbrc:

require 'irb/ext/save-history'
IRB.conf[:SAVE_HISTORY] = 10_000
IRB.conf[:HISTORY_FILE] = ENV['IRB_HISTFILE']
Enter fullscreen mode Exit fullscreen mode

E agora definir não somente a variável HISTFILE como também
as variáveis IRBRC e IRB_HISTFILE, assim:

HISTFILE=/app/dotfiles/.bash_history
IRBRC=/app/dotfiles/.irbrc
IRB_HISTFILE=/app/dotfiles/.irb_history
Enter fullscreen mode Exit fullscreen mode

Uma nota importante sobre o IRB, se você deixar o arquivo .irbrc na raiz, toda vez que você abrir o IRB, ele vai usar o .irbrc do projeto, visto que ele é encontrado primeiro. Isso pode não ser desejado, talvez você queira usar o seu próprio IRB normal. Nesse caso, colocar o arquivo .irbrc dentro de outro diretório, como dotfiles/, passa a ser essencial.

Obrigado por lerem! (:

Discussion (0)