DEV Community

Cover image for Bash history inside Docker Containers
Lucas Perez
Lucas Perez

Posted on

18 6

Bash history inside Docker Containers

🇵🇹 Versão em português deste texto aqui! 🇧🇷

I don't know about other people, but I love having a docker development environment. Being able to just run a docker container with all the dependencies taken care of for all projects, handling versions and etc is just too good.

But what I don't love is when I exit the container and later start it again to realize I have lost all the previous commands, so I can neither crtl+R nor up/ctrl+P to find them. Sad times!

So I decided to try to keep this history, and in order to figure out how to do that, I first thought, how does bash itself knows the previous commands?

It turns out there is an env var named HISTFILE, which will contain a path to a text file with the bash history. Apparently, by default it is set to $HOME/.bash_history.

OBS: If your container does not run bash, but rather some other shell, we would have to find out where this other shell puts its history file.

So a workaround I have found is to change this env var to somewhere else, somewhere inside the project's dir that I'm working on to avoid losing it after stopping the container.

Lets say that the docker image builds a /app folder with all the contents of the directory of the project I'm working on inside it, I could set HISTFILE to /app/.bash_history, and if we map with a volume with the project's dir contents, I would have a persistent history of commands between docker sessions. The file name itself doesn't even have to be .bash_history, it could be something like /app/.docker_bash_history, for example.

To start a container with a specific variable, we can use the -e option:

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

If we are using Docker Compose, we could either pass an env file or the direct variables to it in the docker-compose.yml (or other config file you may be using):

# example config file

services:
  app:
    build: .
    volumes:
      - .:/app # mapping this volume to persist modifications to our new history file
    command: echo Hi!
    env_file: # we can define the variables inside the .env file
      - .env
    environment: # or we can pass them directly here
      HISTFILE: /app/.bash_history
Enter fullscreen mode Exit fullscreen mode

A problem with this approach arises, though. I now have a new file in my project's root, a file that git will see, unless we put it in our .gitignore, and I really think we should. I don't want to commit my history nor do I want to pull other people's history, because this would defeat the purpose of having a history file. Other than that, I just created a new file in the root, which could cause some noise and litter the root folder. Maybe you can find a better place other than the app's highest level folder.

And that's pretty much it. I don't know how bad or good of an idea this is, but I'm enjoying it so far. I created a dotfiles/ folder inside the root that also has other dot files, like .irb_history and .irbrc in a ruby project. In order to get it working, I had to put this in 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

And then define not only HISTFILE, but also IRBRC and IRB_HISTFILE environment variables, like this:

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

An important note on IRB, if you leave the .irbrc file in the root folder, everytime you fire up IRB, it is going to use the project's .irbrc, since it is the first found config file for IRB. This could be undesirable, though. In this case, putting the .irbrc inside another directory, like dotfiles/, becomes essential.

Thanks for reading! (:

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (1)

Collapse
 
andrewbaisden profile image
Andrew Baisden

Good tutorial.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️