Initialise Rails API backend and VueJS App Frontend in Docker for development
Tags: docker, rails, vue, beginners
Published: 2020-06-16 04:29:20

Some systems don’t support development especially ruby on rails development environment is quite difficult in WindowsOS. So by docker we can do development in any machine. The difficulty is initialising the project.

## Install docker
You can install docker by going to [dockerhub](https://hub.docker.com/search/?type=edition&offering=community). The settings I use for docker are 8GB RAM.

## Init Project
Create a folder named `todo` in your working directory. and create a file named `docker-compose.yml` in the folder.

## Init Rails

### Define the project

Create a folder in `todo` folder named `api` and create a file named `Dockerfile` and put the following content there:

`todo/api/Dockerfile`:
```Dockerfile
FROM ruby:2.6.6
RUN apt-get update -qq && apt-get install -y postgresql-client
RUN mkdir /api
WORKDIR /api
COPY Gemfile /api/Gemfile
COPY Gemfile.lock /api/Gemfile.lock
RUN mkdir -p /api/log && touch /api/log/development.log
RUN gem install bundler
RUN bundle install
COPY . /api
RUN gem install foreman
```

**What this file will do:**
_In this file we are telling docker to use image of ruby 2.6.6 and then add postgresql-client that we will be using in project. Then will create a folder in image name `api` and then copy Gemfile and Gemfile.lock in the folder and logs as well the run bundle install and then install foreman that we will be using._

Now create another file in `api` folder named `Gemfile` and add the following content:

`todo/api/Gemfile`:
```ruby
source 'https://rubygems.org'
gem 'rails', '~> 6.0', '>= 6.0.3.1'
```

**What this file will do:**
_ creates a bootstrap Gemfile which just loads Rails. It’ll be overwritten in a moment by rails new._

Also create a file named `Gemfile.lock` in the same folder.

Now create a file named `Procfile` in the same folder with contents:

`todo/api/Procfile`:
```bash
web: bundle exec rails s -b 0.0.0.0 -p ${PORT}
logger: tail -f log/development.log
```

Now in main todo folder create a file named `docker-compose.yml` with following content:

`todo/docker-compose.yml`:
```yaml
version: "3"
services:

  db:
    image: postgres
    volumes:
      - db:/var/lib/postgresql/data
    ports:
      - "5491:5432" # use port that you want to in your local instead of 5491
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust

  api:
    build: ./api
    command: bash -c "rm -f /api/tmp/pids/server.pid && foreman start -f /api/Procfile"
    environment:
      - PORT=3000
    volumes:
      - ./api:/api
      - rails_log:/api/log
    ports:
      - "3091:3000" # use port that you want to in your local instead of 3091
    depends_on:
      - db

volumes:
  db:
  rails_log:
```

### Build the project
With those files in place, you can now generate the Rails skeleton app using docker-compose run:

```bash
docker-compose run api rails new . --api -T --force --no-deps --database=postgresql
```

This will initialise the rails app. Now update a database.yml file in newly created app with following:

`todo/api/config/database.yml`:
```yaml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db # add this host
  username: postgres
  password:
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
```

Now we can boot up the project by going in your `working-directory/todo/` in terminal:

```bash
docker-compose up -d --build
```
Then run:
```bash
docker-compose run api rails db:create
```
Now open the url in browser [http://localhost:3091](http://localhost:3091) and hopefully you will see this image or feel free to comment.
![Rails Init View](https://dev-to-uploads.s3.amazonaws.com/i/v6zu747q26kdkzp0o3qq.png)
All other commands in rails can be called by initialising with `docker-compose run api ....`

## Init VueJS
Create a new folder named `todo/front`. Run the following command in terminal:
```bash
cd front && docker run --rm -v "${PWD}:/$(basename `pwd`)" -w "/$(basename `pwd`)" -it node:14.4-alpine sh -c "yarn global add @vue/cli && vue create ."
```

Then go through options and that will create new vue app according to your options.

Now in `front` folder create a file named `Dockerfile` and fill with following contents:

`todo/front/Dockerfile`:
```bash
FROM node:14.4-alpine
WORKDIR /front
COPY package*.json ./
RUN yarn install
COPY . .
CMD ["yarn", "serve"]
```

Then update the `docker-compose.yml` file in main folder so that final file becomes:

`todo/docker-compose.yml`:
```yaml
version: "3"
services:

  db:
    image: postgres
    volumes:
      - db:/var/lib/postgresql/data
    ports:
      - "5491:5432" # use port that you want to in your local instead of 5491
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust

  api:
    build: ./api
    command: bash -c "rm -f /api/tmp/pids/server.pid && foreman start -f /api/Procfile"
    environment:
      - PORT=3000
    volumes:
      - ./api:/api
      - rails_log:/api/log
    ports:
      - "3091:3000" # use port that you want to in your local instead of 3091
    depends_on:
      - db

  front:
    build: ./front
    ports:
      - "8091:8080" # use port that you want to in your local instead of 8091
    volumes:
      - ./front:/front
      - front_node_modules:/front/node_modules

volumes:
  db:
  rails_log:
  front_node_modules:
```

Now in terminal run:
```bash
docker-compose down -v

docker-compose up -d --build

docker-compose run api rails db:create
```

Run [http://localhost:3091](http://localhost:3091) and [http://localhost:8091](http://localhost:8091) and rails will be running on port 3091 and vuejs front app at 8091.
![Vue Init View](https://dev-to-uploads.s3.amazonaws.com/i/aagezrpc4wkyg9li1mal.png)
---- 
Happy Coding!