In a previous post about Docker for Mac,
I described a way to make SSH keys available inside of Docker containers–here’s
a simpler approach with a few advantages over my previous suggestion. Docker
volumes allow you to link directories from your host machine to the Docker
container, even if the host location is outside of the directory with your
SSH volume configuration
Expose your local
~/.ssh directory as a read-only directory in your Docker
# docker-compose.yml version: '3' services: web: volumes: - .:/myapp - ~/.ssh:/root/.ssh:ro ...
Code running in your Docker container will now have read-only copies of your ssh
directory available, meaning your
id_rsa will be used for installing
dependencies, and any aliases you have defined in your
~/.ssh/config will be
Because the files are mounted as a volume, each user can rely on the same base Docker image, but configure their volume to mount files that are relevant for their usage.
Other applications of volumes
The same approach can be used for other types of credentials–I’ve used the same
pattern for the AWS CLI by mapping
/root/.aws as a read-only volume. This allows most AWS tools, from the CLI, to
the Python Boto3 SDK, to the Elixir ExAws library to access your credentials
and AWS profiles with minimal or no configuration.
For dependencies installed by package managers, such as Ruby’s Bundler
and Elixir’s Mix, I was previously
building dependencies into the images built with a
Dockerfile. This process
allows us to reuse Docker images with exact package versions already installed,
but requires rebuilding the image when any package is added or updated.
In this case, our application dependencies are installed through a single
mix deps.get, which must be rerun to build the
Dockerfiles execute each
RUN command line by line and caches
the filesystem after each line. Docker executes from the previous cached step,
so it must reinstall all packages from your package manager, not just the
Alternatively, we can create a persistent volume in Docker Compose to store our installed dependencies, but not bake them into the image itself.
# docker-compose.yml version: '3' volumes: _deps: bundle: services: web: volumes: - _deps:/myapp/_deps - bundle:/bundle
Now, to update dependencies, we run a single
docker-compose run web bundle or
docker-compose run web mix deps.get to update our Ruby or Elixir dependencies,
and only changes are installed.