Use Docker as Rails Development Environment

Docker container can be used effectively as a rails development environment. Lets create new rails application with Docker and docker-compose.


We are going to see following in this blog

  1. Create new rails application
  2. Persisting Postgres data
  3. Persisting installed gems
  4. Commands

Dockerfile will have the image definition and docker-compose file will contains container configuration.

  1. Create new rails application

[code]
FROM ruby:2.3.3
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
[/code]

We are pulling ruby 2.3.3 image and installing nodejs. Directory /myapp will be created inside container.

Next step would be creating docker-compose file to define and links container.

[code]
version: ‘3’
services:
db:
image: postgres
web:
build: .
command: bundle exec rails s -p 3000 -b ‘0.0.0.0’
volumes:
– .:/myapp
ports:
– “3000:3000”
depends_on:
– db
[/code]

First line indicate the version of docker-compose file. Version 3 has lots of functionality added on it.

Docker compose file contains two services web and db, for web image will be build from Dockerfile and for db postgres image will be pulled from registry.

Current directory will be shared inside container’s /myapp directory and container’s port 3000 will be shared exposed outside to host machine. So that the application will be accessible.

depents_on tag will create link between db and web, so that web can access the db service. We are done with configuration, lets create new rails application.

[code]
$ docker-compose build
$ docker-compose run web rails new . –force –database=postgresql
[/code]

This will create new rails application and the files will be available in current working directory.

Lets modify the database.yml to connect with db.

[code]
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password:
pool: <%= ENV.fetch(“RAILS_MAX_THREADS”) { 5 } %>
development:
<<: * default

database: myapp_development
[/code]

Note the host, its contain name of db service. Since we used depends_on, host db will be accessible.

Lets create the db and launch the application.

[code]
$ docker-compose run web bundle exec rake db:create
$ docker-compose up
[/code]

Navigate to browser to see the welcome page http://localhost:3000

Now lets try to stop and down the container and start the app again.

[code]
CTL +C to stop
$ docker-compose down
$ docker-compose up
[/code]

Now lets try to navigate the url http://localhost:3000,

It will show the FATAL error. Because db container was stopped and all data reset. To solve this problem lets share the container volume to host to persists the db information.

2. Persisting Postgres data

Lets share the db volume to host

[code]
version: ‘3’
services:
db:
image: postgres
volumes:
– /usr/data/volumes/pgdata/etc:/etc/postgresql
– /usr/data/volumes/pgdata/log:/var/log/postgresql
– /usr/data/volumes/pgdata/data:/var/lib/postgresql/data
web:
build: .
command: bundle exec rails s -p 3000 -b ‘0.0.0.0’
volumes:
– .:/myapp
ports:
– “3000:3000”
depends_on:
– db
[/code]

db volumes are shared in /usr/data/volumes/pgdata directory. Now the data will be persist.

3. Persisting installed gems

Similarly bundle install will be running every time on container restart. Lets share the volume of bundle.

[code]
version: ‘3’
services:
db:
image: postgres
volumes:
– /usr/data/volumes/pgdata/etc:/etc/postgresql
– /usr/data/volumes/pgdata/log:/var/log/postgresql
– /usr/data/volumes/pgdata/data:/var/lib/postgresql/data
web:
build: .
command: bundle exec rails s -p 3000 -b ‘0.0.0.0’
volumes:
– .:/myapp
– /usr/data/volumes/bundle:/bundle
ports:
– “3000:3000”
environment:
– BUNDLE_PATH=/bundle
depends_on:
– db
[/code]

Note the environment variable BUNDLE_PATH= /bundle. Gems will be installed in /bundle directory and that will be shared to /usr/data/volumes/bundle.

4. Commands

Create migration

[code]$ docker-compose run web bundle exec rails g migration add_column_to_table[/code]

Precompile assets

[code]$ docker-compose run web bundle exec rake assets:precompile
[/code]

Bundle install

[code]$ docker-compose run web bundle install[/code]

 

To know more on running rails application with web server, click https://medium.com/@sivakumarvadivelu/build-and-run-rails-application-with-docker-and-docker-compose-8c3601af2765

Leave a comment