First of all, why Docker?
At some point, I'm tired of installing these different applications on my mac. I need c++, python, ruby, mysql, postgresql etc all for different purposes. And once a while you will need a new version of all the packages. Having Docker removes the issue of having to dig into the code and fix every dependency once a while. Moreover, when I really need to fix something, since everything is documented in Dockerfile
, it's easier for me to debug.
Here's the setup
For my simple Rails application, I only need two files, a Dockerfile
to dockerize my application and a docker-compose.yml
to config all the docker containers to run at development time. Here my Dockerfile
:
FROM ruby:2.7.1
# this is required for installing yarn
RUN curl https://deb.nodesource.com/setup_12.x | bash
RUN curl https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y nodejs yarn postgresql-client
# throw errors if Gemfile has been modified since Gemfile.lock
RUN bundle config --global frozen 1
WORKDIR /usr/src/app
# install all gems
COPY Gemfile Gemfile.lock ./
RUN bundle install
# copy all the files to the working directory
COPY . .
RUN yarn install
This file basically installs node
, yarn
, postgresql-client
, and all the required gems. Then, here's my docker-compose.yml
:
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
web:
build: .
ports:
- "3000:3000"
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/usr/src/app
depends_on:
- db
This file boots up two containers. One for postgres and one for my Rails application. Something worth mentioning is that I mounted my root directory to /usr/src/app
so that the Rails server will reflect any of my changes. This allows me to not rebuild and rerun the server every time I change something.
Oh, since postgresql is setup in a docker container, I need to set database.yml
as follow:
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
pool: 5
development:
<<: *default
database: ${app_name}_development
Using plain text as password is as bad as one cound think but since this is only use in the development environment, it's fine.
Some more setup
Since it is the first time your application connects to the db, you will need to run the folloing to build:
docker-compose up --build
Then, in a different terminal window:
docker-compose run web rails db:create
docker-compose run web rails db:migrate
Lastly, how to boot them up?
Simply run:
docker-compose up
And if you want the taste of npm run dev
, you can add the following to your Rackfile
:
task :dev do
system 'docker-compose up'
end
Then you can run rails dev
like a charm.
Dependency Updates
Once a while you'll need to update your Gemfile
or package.json
, and you'll get the package not found error. That is because bocker containers are fixed after they're built. To rebuild, run docker-compose up --build web
to force rebuild the web container. Things should work as expected afterwards.