Skip to content

Latest commit

 

History

History
133 lines (93 loc) · 3.6 KB

07-dockerfile.md

File metadata and controls

133 lines (93 loc) · 3.6 KB

Dockerfile

A Dockerfile is a file that contains a set of instructions that describe an environment configuration.

Let try to create rails docker image using Dockerfile. First, create a project folder:

mkdir ~/myapp
cd ~/myapp

Create Dockerfile with the following content in the project root folder:

FROM ruby:2.6.3

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn

WORKDIR /usr/src/app

COPY Gemfile /usr/src/app
COPY Gemfile.lock /usr/src/app/Gemfile.lock
RUN bundle install
COPY . /usr/src/app

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

Let explain it line by line:

We are using docker image ruby with tag 2.6.3 as the base image to build out our custom image. Visit https://hub.docker.com to see what images are available to choose.

FROM ruby:2.6.3

Then we update the image packages and install nodejs, postgresql-client, and yarn packages for our rails application.

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn

This line set /usr/src/app folder as the workdir inside our image container.

WORKDIR /usr/src/app

Copy package.json and yarn.lock to project root folder inside the container. Then run yarn install --check-files to install npm packages.

COPY package.json /usr/src/app
COPY yarn.lock /usr/src/app
RUN yarn install --check-files

Copy Gemfile, and Gemfile.lock to image first, then run bundle install to install ruby gems inside the images. After that copy the remain project files/folders into the image. As docker using layer caching for each RUN, COPY and ADD commands, copy Gemfile and Gemfile.lock before copy entire source code can leverage docker layer caching which in term saving time for install the ruby gem dependencies.

COPY Gemfile /usr/src/app
COPY Gemfile.lock /usr/src/app/Gemfile.lock
RUN bundle install
COPY . /usr/src/app

Now, copy entrypoint.sh script to container folder /usr/bin/ and given the execute permission to that file. Set the ENTRYPOINT to run entrypoint.sh every time the container startup. Then, expose port 3000 for outside to connect.

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

Finally, we set the default command to run when no command has specified for running the container.

CMD ["rails", "server", "-b", "0.0.0.0"]

Create an empty package.json and yarn.lock files

touch package.json
touch yarn.lock

Create a bootstrap Gemfile which load Rails. It'll be overwritten in a moment by rails new.

source 'https://rubygems.org'
gem 'rails', '~> 6.0.0'

Create an empty Gemfile.lock to build our Dockerfile.

touch Gemfile.lock

Next, provide an entrypoint script to fix a Rails-specific issue that prevents the server from restarting when a certain server.pid file pre-exists. This script will be executed every time the container gets started. entrypoint.sh consists of:

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /usr/src/app/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

Right now we can try to build a docker image and tag it as myapp

docker build -t myapp .

You can verify the image by:

docker images

Next: Docker Compose