Histórico do Bash dentro de Contêineres Docker
Tags: docker, bash, todayilearned
Published: 2022-05-25 13:10:13

🏴󠁧󠁢󠁥󠁮󠁧󠁿 English version of this text [_here_](https://dev.to/lucassperez/bash-history-inside-docker-container-553g)!

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`:

```sh
docker exec -it -e HISTFILE=/app/.bash_history -v <volume> <...outras coisas...>
```

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):

```yml
# 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
```

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`:

```rb
require 'irb/ext/save-history'
IRB.conf[:SAVE_HISTORY] = 10_000
IRB.conf[:HISTORY_FILE] = ENV['IRB_HISTFILE']
```

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

```sh
HISTFILE=/app/dotfiles/.bash_history
IRBRC=/app/dotfiles/.irbrc
IRB_HISTFILE=/app/dotfiles/.irb_history
```

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! (: