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!
Are you ready to build something brilliant? We're ready to help.