I was curious to see if I could create a Docker container for a new Rails project without having Ruby or Rails installed on the host machine. To do this I created a new Ubuntu 18 virtual machine with the bare minimum installed for the OS. I also install Docker, RubyMine, and DataGrip.
Initially I was hoping I could just create the new project inside RubyMine. Unfortunately I couldn’t get it working. As you will see setting up the initial Docker container requires more then just running the “docker-compose up” command.
My main resource in setting up the image was Docker Rails Quickstart Guide. The basic plan is:
- Setup Ruby Docker container.
- Add default Gemfile for Rails. Required to create new Rails application.
- Create a new Rails application but don’t build the container yet.
- Update the configuration files.
- Build the docker container to install the Gems.
I started off as they recommended and created an empty folder with Dockerfile.
FROM ruby:2.5 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /website WORKDIR /website COPY Gemfile /website/Gemfile COPY Gemfile.lock /website/Gemfile.lock RUN gem install bundler RUN bundle install COPY . /website
I then created a basic Gemfile and empty Gemfile.lock file.
source 'https://rubygems.org' gem 'rails', '5.2.0'
Finally I created the docker-compose file.
You might have noticed this file is a bit different then the one in the Docker Quickstart. I made these changes after the contain failed to build and/or I couldn’t connect to it with RubyMine.
version: '2' services: db: image: postgres ports: - "5432:5432" environment: POSTGRES_PASSWORD: password1234 volumes: - ./tmp/db:/var/lib/postgresql/data web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/website ports: - "3000:3000" depends_on: - db
The first change I made was downgrading the version from 3 to 2 as RubyMine currently only supports 2. I also added ports and a password for the Postgres database so I can access from DataGrip. If you don’t set the port and password your Rails application will be able to access the database but nothing else will.
I then created the rails application as recommended by the quickstart guide. Since this is the first time running it pulls down the docker files. Then I ran into the first of many permission errors.
docker-compose run web rails new . --force --database=postgresql
This permission error was caused by the Postgres container. The files created Docker images are usually owned by root but some of the temporary Postgres files where also owned by VBoxAdd.
After a while I figured out the way to fix this was to run the following command:
sudo chown -R $USER:$USER .
I got several permission errors during my trails and error of setting up the Rails container. Every time I would just run the above command to fix it.
Once the permission errors went away I was able to create a new rails application. Before the files for the new rails application where created it needs to build the Docker container so don’t be surprised to see the below.
Your newly created rails files might be owned by root. In this case run the command you have probably become very familiar with:
sudo chown -R $USER:$USER .
Notice that the Gemfile has been updated and populated with all the Gems needed to run a new rails application.
Since we just called run on the web Docker container non of the installed Gems where saved in the container. To prevent having to re-install the gems every time the container is run we need to build it.
Now the web container is ready but our database isn’t. Open up the database config file and set the host, username, and password.
Now create the Rails databases.
docker-compose run web rake db:create
Again if you get permission errors trying to create the databases run change permissions command.
sudo chown -R $USER:$USER .
Now bring up the containers and you should be see the Welcome to Rails website.
docker-compose up
The site is working but now we need to get it working with RubyMine. If you use a different editor then your steps might be different.
First stop the containers using Ctrl-C.
To safe us some steps later lets update the Gemfile. By default Rails installs the Byebug gem for debugging. RubyMine likes the Ruby Debug IDE gem. Just don’t run them both at the same time as they don’t play well together.
Remove ByeBug from the Gemfile and add Ruby Debug IDE. Your Gemfile will look like:
Now rebuild the Docker container so the new gems are installed.
docker-compose build
Then open up RubyMine and open up your project. Once it’s open we need to tell RubyMine about our Docker containers. To this go to File–>Settings. Then go the Build, Execution, Deployment–>Docker in the Settings dialog and make sure Docker is setup correctly. If it is you should see something similar to the below.
You might be missing Docker Machine in which case you can install it following these instructions. Try re-opening RubyMine and if it still does not find Docker Machine then you will need to tell it the exact path.
Now that Docker is setup correctly in RubyMine we need to setup the Ruby SDK by going to Languages & Frameworks –> Ruby SDK and Gems in the Settings dialog. Assuming you don’t have Ruby installed on your local workstation the list of Ruby SDKs should be empty. Click the green plus sign to add one and choose New Remote.
In the Configure Remote Ruby Interpreter select Docker Compose and enter in the settings shown below. This tells RubyMine what Docker Compose file to use to build the containers and container is the website.
After you click OK RubyMine will run the Docker containers and attempt to find Ruby in the container. It will also attempt to find all the gems installed on the container. This can take a couple minutes but if everything works correctly you should see something like:
Sometime the correct Ruby version will be listed by the gems won’t be shown. To fix you might have to remove the newly added Ruby SDK by clicking the minus sign and try again.
If RubyMine can’t load the Docker containers then it will probably display a very unhelpful error message. Try going back to the terminal and running docker-compose up manually. If you get any errors fix them then try configuring RubyMine again.
Assuming everything is working correctly you should be able to run and debug the application. To test that debugging works put a break point then try debugging.
Now you can develop your new app without installing Ruby or Rails on your local workstation. If you have any tips for dealing with the Docker Prostgres permission issues let me know at chris.cumming@saturdaymp.com.
P.S. – My wife recently introduced me to the band Walk of the Earth which we get to see live shortly. They are most famous for all the band members covering Gotye’s “Somebody That I used Know” a single guitar but my favourite song is an original called “Rule the World“.
They said no way
I say I rule the world
(Ain’t afraid of the walls, I’mma break them down)
They stay the same
Well, I’m feelin’ high as a bird
(Ain’t afraid of the ground, I’mma stand up)