Can't find the Rakefile in a docker-compose environment

Hi all,

I’m currently in the process of taking a Ruby on Rails proyect into CircleCI to run the build and test cycle. However, I’m having trouble because this proyect uses Docker Compose and I’ve managed to run the build step and to start the project, but running migrations throws an error I can’t understand.

The proyect uses 3 Docker images. Here’s the docker-compose.yml file:

Docker Compose YAML
version: '3'
services:
  postgres:
    image: postgres:10.3
    ports:
      - "5432"
    env_file:
      - .env
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    env_file:
      - .env
    command: bash -c "rm -f tmp/pids/server.pid && (bundle check || bundle install) && bundle exec whenever --update-crontab --set environment=${RAILS_ENV} && cron && bundle exec rails s -p 4000 -b '0.0.0.0'"
    volumes:
      - .:/var/www/web
    ports:
      - "4000:4000"
    depends_on:
      - postgres
  nginx:
    build:
      context: .
      dockerfile: Dockerfile_nginx
    depends_on:
      - web
    links:
      - web
    ports:
      - "3000:80"

The postgres image is downloaded from Docker Hub. The other two are defined as follows:

Here’s the web Dockerfile:

web Dockerfile
FROM ruby:2.5.0

ENV LANG C.UTF-8

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev software-properties-common

# Node.js
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - \
    && apt-get install -y nodejs

# yarn
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -\
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
    && apt-get update \
    && apt-get install -y yarn

ENV APP_HOME /var/www/web
ENV RAILS_ROOT /var/www/web

RUN mkdir -p $RAILS_ROOT
WORKDIR $RAILS_ROOT

ADD Gemfile $RAILS_ROOT/Gemfile
ADD Gemfile.lock $RAILS_ROOT/Gemfile.lock
RUN gem install bundler
RUN bundle install --binstubs --jobs=3 --retry=3
COPY . .
RUN mkdir -p $RAILS_ROOT/log
RUN touch $RAILS_ROOT/log/cron.log

EXPOSE 4000
CMD cron -f && bundle exec puma
ADD . $RAILS_ROOT

And here’s the nginx Dockerfile:

nginx Dockerfile
# Base image
FROM nginx

# Install dependencies
RUN apt-get update -qq && apt-get -y install apache2-utils

# establish where Nginx should look for files
ENV RAILS_ROOT /var/www/web

# Set our working directory inside the image
WORKDIR $RAILS_ROOT

# create log directory
RUN mkdir log

# copy over static assets
COPY public public/

# Copy Nginx config template
COPY nginx.conf /tmp/docker.nginx

# substitute variable references in the Nginx config template for real values from the environment
# put the final config in its place
RUN envsubst '$RAILS_ROOT' < /tmp/docker.nginx > /etc/nginx/conf.d/default.conf

EXPOSE 80
# Use the "exec" form of CMD so Nginx shuts down gracefully on SIGTERM (i.e. `docker stop`)
CMD [ "nginx", "-g", "daemon off;" ]

In order to have both of those images available on CircleCI, I’ve uploaded them to Docker Hub. I can use them, then, from my config.yml file:

CircleCI config YAML
version: 2
jobs:
  build:
    working_directory: .

    docker:
      - image: felix91gr/proyesp-backend-main:0.0.2
      - image: postgres:10.3
      - image: felix91gr/proyesp-backend-nginx:0.0.1

    steps:
      - checkout

      - setup_remote_docker

      - run:
          name: Install Docker client
          command: |
            set -x
            VER="17.03.0-ce"
            curl -L -o /tmp/docker-$VER.tgz https://get.docker.com/builds/Linux/x86_64/docker-$VER.tgz
            tar -xz -C /tmp -f /tmp/docker-$VER.tgz
            mv /tmp/docker/* /usr/bin

      - run:
          name: Install Docker Compose
          command: |
            set -x
            curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
            chmod +x /usr/local/bin/docker-compose

      - run:
          name: Build service
          command: docker-compose build

      - run:
          name: Run the backend daemon
          command: docker-compose up -d

      - run:
          name: Put it down 
          command: docker-compose down

      - run:
          name: Run the migrations
          command: |
            docker-compose run web rake -f ./Rakefile db:create db:migrate

This doesn’t work, this is the error I get:

====>> Run the migrations
  #!/bin/bash -eo pipefail
docker-compose run web rake -f ./Rakefile db:create db:migrate

Creating network "web_default" with the default driver
Creating web_postgres_1 ... done
rake aborted!
No Rakefile found (looking for: ./Rakefile)
/usr/local/bundle/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
(See full trace by running task with --trace)
Error: Exited with code 1
Step failed
Error: runner failed
Task failed

I realized there must be an error in my setup because when I run the command docker-compose run web ls in local, I see this:

Dockerfile	  Rakefile     config.ru	   nginx.conf	      tmp
Dockerfile_nginx  apiary.apib  db		   package-lock.json  vendor
Gemfile		  app	       doc.md		   public
Gemfile.lock	  bin	       docker-compose.yml  spec
README.md	  config       lib		   test

Whereas when I run the same command in my config.yml I see this:

^@^@tmp

Clearly there’s a mismatch. What’s the error? Sorry for my noviceness, it must be something really obvious that I’m just not seeing.

Thanks for your patience, and have a good day!

The strange character sequence ^@^@ is exactly the same one I got with an unrelated problem, and that you have got it as well makes me wonder if it is a CircleCI bug:

However, I would not be sure this is the cause of your overall problem - it seems like there’s a default directory issue. What happens if you run this?

docker-compose run web ls /var/www/web

If that gives you correct results, could you try this?

docker-compose run web \
    cd /var/www/web && \
    rake -f ./Rakefile db:create db:migrate

In the end I needed to run Circle in machine mode instead of docker mode.

The problem was that docker mode doesn’t allow for volume mounting, which clashed with the way this project is configured (the docker images web and postgres share volumes with its orchestrator).

This is my final config.yml file:

jobs:
  build:
    machine: 
      enabled: true
      image: circleci/classic:latest
    
    working_directory: ~/project

    steps:
      - checkout

      - run:
          name: Build service
          command: docker-compose build

      - run:
          name: Put the backend up and down in preparation for the migrations
          command: |
            docker-compose up -d
            docker-compose down

      - run:
          name: Run the Rakefile
          command: |
            docker-compose run web rake db:create db:migrate

      - run:
          name: Put the backend up again
          command: docker-compose up -d

      - run:
          name: Run the test suite
          command: |
            docker-compose exec web bundle exec rspec

Aha, this is true! Good find. :smiley_cat:

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.