Build and Run Rails Application with Docker and Docker Compose

Sivakumar V

1 min read

Docker compose is a tool for running multi-container docker application. Container configuration are maintained easily with docker compose. Before proceed, know basics of docker (how to build and run simple container application).
For docker compose installation help click here https://docs.docker.com/compose/install/. Lets create simple rails application and run it with docker compose.
Define Dockerfile
Check the docker and docker-compose are installed properly.

$ docker --version
Docker version 17.03.1-ce, build c6d412e
$ docker-compose --version
docker-compose version 1.12.0, build b31ff33

Lets build rails container by defining the Dockerfile and place it in the application root. Overall file structure.

Dockerfile

FROM ruby:2.2.0
FROM ruby:2.2.0
COPY . /my-rails-app
RUN apt-get update -qq
RUN apt-get install -y build-essential
RUN apt-get install -y nodejs npm
# for postgres
RUN apt-get install -y libpq-dev
ENV APP_HOME /my-rails-app
WORKDIR $APP_HOME
ADD . $APP_HOME/
RUN bundle install

This will create container with ruby, nodejs and pg-dev package, application will be copied to container /my-rails-app directory
Lets create nginx upstream to listen application port 3000. Create nginx folder in application root. It will contain two files nginx.conf and Dockerfile.
Dockerfile (For Nginx)

FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf

nginx.conf (To listen application port 3000)

worker_processes 4;
events { worker_connections 1024; }
http {
  upstream web-app {
  least_conn;
  server app:3000 weight=10 max_fails=3 fail_timeout=30s;
  }
  server {
  listen 80;
  location / {
  proxy_pass http://web-app;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection 'upgrade';
  proxy_set_header Host $host;
  proxy_cache_bypass $http_upgrade;
 }
}
}

Note the upstream, its listening web container port 3000.
Define Docker Compose file
Lets define web, db and app containers and link them to make it work together.
docker-compose.yml

webserver:
  build: ./nginx
  ports:
    - "80:80"
  links:
    - app:app
db:
  image: postgres:9.4.1
  ports:
    - "5432:5432"
  environment:
    - POSTGRES_PASSWORD=password
  volumes:
    - /home/user/pgdata/etc:/etc/postgresql
    - /home/user/pgdata/log:/var/log/postgresql
    - /home/user/pgdata/lib:/var/lib/postgresql
app:
  build: .
  command: bin/rails server --port 3000 --binding 0.0.0.0
  links:
    - db
  volumes:
    - .:/my-rails-app
  volumes_from:
    - bundle
  ports:
    - "3000"
bundle:
  image: ubuntu
  volumes:
    - /home/user/volumes/appbundle:/bundle

webserver- Nginx Container configuration. Its going to expose port 80
db – Database PostgreSQL Container configuration. Its going to expose port 5432
app – Rails application configuration. Its going to start webrick server on port 3000.
Note the db volumes, it will share the postgres data with host machine, so that data will be persist even after re-create the container.
Find the container environment variables.

docker-compose run app env

This will list all environment variables. Database host has to be copied to database.yml. Update database.yml

development:
  adapter: postgresql
  encoding: unicode
  database: demo_db01
  username: postgres
  password: postgres
  pool: 5
  host: <%= ENV['DB_1_PORT_5432_TCP_ADDR'] %>

Build and Run the Container
Done with configuration. Lets build and run the container.

docker-compose build
docker-compose up

Navigate to http://localhost to see you the application home page. DB migration tasks can be run inside the app container. Lets connect with app container.

docker-compose run app bash
rake db:migrate

Thanks for reading. 🙂

Related posts:

Leave a Reply

Your email address will not be published. Required fields are marked *