The Importance of the .dockerignore File

For a while now, I have been using Docker for local development on my Ruby on Rails applications. This has worked out great and I've spent plenty of time tweaking Docker to suit my needs, as things have changed. I recently started a new initiative to use Docker in a production environment, not just for local development. Unfortunately, I hit a little hiccup.

Setting Up Docker: The Problem

If you are like me, the first time you configured your Dockerfile for Ruby on Rails, you found a guide to set up your Dockerfile. It was great for setting up a local development environment. It probably had you set up a Dockerfile, create a docker-compose.yml file, and set up a build and run process.

Here is a very abbreviated example of my Dockerfile

```bash

FROM ruby:2.5.3

###############################################################################

# Base Software Install

###############################################################################

RUN curl -sL https://deb.nodesource.com/setup_$RAILSDOCK_NODE_VERSION.x | bash -

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \

 echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

.

.

.

###############################################################################

# Ruby, Rubygems, and Bundler Defaults

###############################################################################

ENV LANG C.UTF-8

.

.

.

ENV RAILS_ENV production

###############################################################################

# Final Touches

###############################################################################

.

.

.

RUN bundle config build.nokogiri --use-system-libraries

RUN bundle check || bundle install

# Copy for package.json and yarn.lock to do install to save layer size

COPY package.json yarn.lock ./

RUN yarn install --check-files --production=true

# Finally copy over rest of app

COPY . /app

# Precompile assets for production

RUN bundle exec rake assets:precompile

.

.

.

```

If you just do the standard tutorials, everything works great in development. But, most of these tutorials don't cover the .dockerignore file. This file is very important and not having one becomes a problem when Docker runs the following line in the above Dockerfile:

```bash

# Finally copy over rest of app

COPY . /app

```

Locking Down Your Docker Image For Production or Sharing

By default, when you run a Docker build and copy your directory into the image, it will grab every single file in your directory: the node_modules, those weird .DS_Store files, and even your .env files that could contain sensitive information. Why is this a problem? If you happen to make your Docker image publicly available after it's built, people can look inside and see those extra files that were included inside. Most Dockerize your Rails app guides don't cover.

The solution is to use a .dockerignore file. It functions exactly like a .gitignore file. Put the files and folder paths that you don't want committed in to your Docker image.

Here is an example of my .dockerignore file.

```bash

**/.classpath

**/.dockerignore

**/.env

**/.git

**/.gitignore

**/.project

**/.settings

**/.toolstarget

**/.vs

**/.vscode

**/*.*proj.user

**/*.dbmdl

**/*.jfm

**/azds.yaml

**/charts

**/docker-compose*

**/Dockerfile*

**/node_modules

**/npm-debug.log

**/obj

**/secrets.dev.yaml

**/values.dev.yaml

README.md

.DS_Store

.bin

.git

.gitignore

.bundleignore

.bundle

.byebug_history

.rspec

tmp

log

test

config/deploy

config/master.key

public/packs

public/packs-test

node_modules

yarn-error.log

coverage/

```

This keeps a lot of development cruft out of my Docker image. Reviewing it, I could probably update it again 😁. Once you add your .dockerignore file to your project, try to build things again.

Now, your Docker container should be leaner (no more extra files you don't need in there) and more secure!