Running a Rails Development Environment in Docker


Reading Time: 9 minutes

As we prepare our new Docker-based infrastructure for running your tests, we’d like to show you how you can use the same environment for development as well. Feel free to follow along as I demonstrate how to move a simple Rails applications into Docker during development.

Suppose we have a (very) simple new Rails application:

gem install rails bundler
rails new demo
cd demo
bundle install

Without any further configuration, this provides us with a Rails application, using SQLite as a database. And if we want to, we can run our tests and start the development server to take a look in our browser.

bundle exec rake test
bundle exec rails server

We can now access the default start page at localhost:3000. It’s not a very useful app, but it’ll do for our purpose.

Now, let’s move this app to use in a Docker-based environment.

Step 1: Installing Docker

If you already have Docker up and running, you can skip this step and move on to Step 2, Dockerizing right away. If not, let’s get Docker running on your machine.

At Codeship, we recommend using Docker Machine. It’s a young project and still in beta, but we’ve had great success using it internally.

See their installation instructions for how to get it running on your computer. Those instructions will include the necessary commands to get Docker itself running as well. Once you have Docker Machine installed, create a new environment (e.g., based on Virtualbox) and configure your local host to use that environment for Docker.


Step 2: Dockerizing a Rails Application

Now that we have Docker installed and running, it is time to get our application running on it. Docker applications are configured via a Dockerfile, which defines how the container is built.

The easiest Dockerfile includes a single line, the base image to use. The following one would, for example, provide an Ubuntu Trusty based system:

FROM ubuntu:14.04

Many images are readily available, and you can search for a suitable base image at the Docker Hub. We’ll use the ruby:2.2 base image.

FROM ruby:2.2 

# Install apt based dependencies required to run Rails as 
# well as RubyGems. As the Ruby image itself is based on a 
# Debian image, we use apt-get to install those.
RUN apt-get update && apt-get install -y \ 
  build-essential \ 

# Configure the main working directory. This is the base 
# directory used in any further RUN, COPY, and ENTRYPOINT 
# commands.
RUN mkdir -p /app 

# Copy the Gemfile as well as the Gemfile.lock and install 
# the RubyGems. This is a separate step so the dependencies 
# will be cached unless changes to one of those two files 
# are made.
COPY Gemfile Gemfile.lock ./ 
RUN gem install bundler && bundle install --jobs 20 --retry 5

# Copy the main application.
COPY . ./

# Expose port 3000 to the Docker host, so we can access it 
# from the outside.

# The main command to run when the container starts. Also 
# tell the Rails dev server to bind to all interfaces by 
# default.
CMD ["bundle", "exec", "rails", "server", "-b", ""]

After adding the above file as Dockerfile to your repository, we can now build the container and start running commands with it. We specify a tag via the -t option, so we can reference the container later on.

docker build -t demo .
docker run -it --rm demo bundle exec rake test
docker run -itP demo

Here are some explanations for the commands above:

  • docker run runs tasks in a Docker container. This is most commonly used for one-off tasks but is also very helpful in development.
  • The -P option causes all ports defined in the Dockerfile to be exposed to unprivileged ports on the host and thus be accessible from the outside.
  • If we don’t specify a command to run on the command line, the command defined by the CMD setting will be run instead.

We now have our Rails application running inside a Docker container, but how do we actually access it from our computer? We will use docker ps, a handy tool to list running Docker processes as well as additional information about them.

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                     NAMES
eb018d2ca6e2        demo           "bundle exec 'rails    10 seconds ago      Up 9 seconds>3000/tcp   pensive_ritchie

We can see the container ID, the image it is based on, which command it is running, and the mapping of any exposed ports. With this information at hand, we can now open the app in our browser http://localhost:32769.

Note: If you don’t have Docker running on your local machine, you need to replace localhost in the above URL with the IP address of the machine Docker is running on. If you’re using Docker Machine, you can run docker-machine ip “${DOCKER_MACHINE_NAME}” to find out the IP.

The application is up and running and accessible from our development machine. But, each time we make a change, we need to build a new container. That’s not very helpful. Let’s improve our setup.

Step 3: Docker Volumes

Docker supports what it calls volumes. These are mount points which let you access data from either the native host or another container. In our case, we can mount our application folder into the container and don’t need to build a new image for each change.

Simply specify the local folder as well as where to mount it in the Docker container when calling docker run, and you’re good to go!

docker run -itP -v $(pwd):/app demo

Step 4: Improvements

Dockerfile Best Practices lists some ways to improve performance and create easy to use Dockerfiles. One of those tips is using a .dockerignore file.


Similar to a .gitignore file, .dockerignore lets us specify which files are excluded and not transferred to the container during the build. This is a great way to speed up the build times, by excluding files not needed in the container (e.g., the .git subdirectory). Let’s add the following .dockerignore file to our project



Because most of the commands we run on the Rails container will be prepended by bundle exec, we can define an [ENTRYPOINT] for all our commands. Simply change the Dockerfile like this:

# Configure an entry point, so we don't need to specify 
# "bundle exec" for each of our commands.
ENTRYPOINT ["bundle", "exec"]

# The main command to run when the container starts. Also 
# tell the Rails dev server to bind to all interfaces by 
# default.
CMD ["rails", "server", "-b", ""]

You can now run commands without specifying bundle exec on the console. If you need to, you can override the entrypoint as well.

docker run -it demo "rake test"
docker run -it --entrypoint="" demo "ls -la"


If you’re not happy with the default locale in your Docker container, you can switch to another one quite easily. Install the required package, regenerate the locales, and configure the environment variables.


# Install apt based dependencies required to run Rails as 
# well as RubyGems. As the Ruby image itself is based on a 
# Debian image, we use apt-get to install those.
RUN apt-get update && apt-get install -y \ 
  build-essential \ 
  locales \ 

# Use en_US.UTF-8 as our locale
RUN locale-gen en_US.UTF-8 


Step 5: Moving your Development Environment to PostgreSQL

While SQLite might be fine for a simple app, you wouldn’t use it in production. So let’s move our development environment over to PostgreSQL instead.

We could add the database to our container, but there’s a better way to do this. Use Docker Compose to provision the database in a separate container and link those two together.

To get Docker Compose installed, please follow the installation instructions on their website.

Basic Compose Configuration

Once this is done, let’s duplicate our configuration to work with Compose. Add a docker-compose.yml file to your repository and include the following configuration:

  build: .
  command: rails server -p 3000 -b ''
    - .:/app
    - "3000:3000"

With the configuration above, running your development environment is as simple as running two commands:

docker-compose build
docker-compose up

Even for a single container environment this has some (smaller) improvements over using docker directly. We can specify the VOLUME definition directly in the configuration file; we don’t need to specify it on the command line. We can also define the port on the Docker host our application will be available at and don’t need to look it up.

Adding PostgreSQL

We could now create a new Dockerfile for running PostgreSQL, but luckily we don’t need to. There is a readily available PostgreSQL Docker image available on the Docker Hub, so let’s just use that instead.

  build: .
  command: rails server -p 3000 -b ''
    - .:/app
    - "3000:3000"
    - postgres
  image: postgres:9.4
    - "5432"

We defined a new container called postgres, based on the PostgreSQL 9.4 image (there are images for previous versions available as well), configured the port on the new image, and told our app container to define a link to the database.

But how do we access the database from within our Rails application? Fortunately for us, Docker Compose exposes environment variables for linked containers, so let’s take a look at those.

# build new container images first
docker-compose build 
docker-compose --rm app env

This will print a bunch of environment variables, including these two:


We can now use those in our database.yml to access the database server.

default: &default 
  adapter: postgresql 
  encoding: unicode 
  pool: 5 
  timeout: 5000 
  username: postgres 
  # please see the update below about using hostnames to 
  # access linked services via docker-compose
  host: <%= ENV['POSTGRES_PORT_5432_TCP_ADDR'] %> 
  port: <%= ENV['POSTGRES_PORT_5432_TCP_PORT'] %>

  <<: *default 
  database: app_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run 
# "rake". Do not set this db to the same as development or
# production.
  <<: *default 
  database: app_test

We also need to change our Gemfile and remove the sqlite3 gem and add pg instead.

# Use PostgreSQL as the database for Active Record.
gem 'pg'

Having made those changes, let’s rebuild our containers and configure the database.

docker-compose build
docker-compose up
docker-compose run app rake db:create
docker-compose run app rake db:migrate

Update, Compose now recommends to use the hostnames instead of environment variables to access linked services. The database.yml mentioned above should now look like the following snippet, further changes are not required.

default: &default 
  adapter: postgresql 
  encoding: unicode 
  pool: 5 
  timeout: 5000 
  username: postgres 
  host: postgres
  port: 5432

Step 5.5: Extending Your Rails Development Environment

With the steps shown above, it’s easy to extend the rails development environment. Need a Redis server? Look for a suitable image on the Docker Hub, extend the docker-compose.yaml configuration file with a few lines, and restart your environment. The same goes for memcached or other services you require.

Want to test against a different Ruby version? Modify the Dockerfile, spin up the environment and run your tests.


Switching your development environment to Docker does take some amount of work, but the benefits are well worth it. You get an environment that’s easy to share with fellow team members, you can model it to closely resemble your production environment, and extend it in a simple way. With Codeship’s upcoming Docker infrastructure, you’ll be able to use the same environment to run your tests on Codeship and then push the built and tested containers to your production servers and deploy them. Easy, fast, efficient, and with less room for errors.

The best part is that it’s easy to clean up once you’re done with a project. You don’t pollute your computer with all those different libraries you only need for that single project!

Extra Resources

PS: If you liked this article you might also be interested in one of our free eBooks from our Codeship Resources Library. Download it here: Automate your Development Workflow with Docker

Posts you may also find interesting:

Architecting Ruby on Rails Apps as Microservices

Subscribe via Email

Over 60,000 people from companies like Netflix, Apple, Spotify and O'Reilly are reading our articles.
Subscribe to receive a weekly newsletter with articles around Continuous Integration, Docker, and software development best practices.

We promise that we won't spam you. You can unsubscribe any time.

Join the Discussion

Leave us some comments on what you think about this topic or if you like to add something.

  • Great article! Thanks!
    It would be nice to have an article teaching how to use Jenkins + Docker to run integration tests.

    • thaold

      hey Santiago, I’m using docker-compose and continuous integration tool (which feels superior then jenkins after using it), you can read more the difference between Jenkins and Go.CD, and even if you want to stick to Jenkins, some concepts and ideas are still valid for jenkins too, check out this article

      • Cool! I Didn’t know about it. Thanks for the tip.

  • jamlee

    building it for me is very difficult ,So Have any built image with dockerfile ? i can’t reach gem

    • The built image I have would be useless for you, as the Gemfile won’t match. Which error message do you get? (Could you share your logs for the `docker build.` step via

  • For those running docker on OSX, and using boot2docker, on Step 2, instead of trying to reach http://localhost:32769 you should use the boot2docker ip instead of localhost (you can get that ip running `boot2docker ip` on your terminal.

    • Adam

      Docker is native now.

  • Christophe Dufour

    Nice article!
    As explained here ( ), I think using host is better than ENV values

    • Uh, I missed that. I’ll take a look and update the article! Thanks for pointing this out!

  • Rick Yu


  • Eagerly awaiting part 2 then! It’s been my stumbling block for starting to use Docker with Rails in dev/test — I want something like guard to be running continuous testing as I develop locally.

  • Nice Article, very informative

  • Alan Willms

    Great article! I only missed how to preserve Postgres data even if its container is discarded.

    • Pietro

      I found this issue quite annoying actually. Do I have to use a kind of “data-container”? I mean something like the one used in this post:

      • You need to use a volume for the PostgreSQL data directory (which by default is `/var/lib/postgresql/data`). That volume can either point to a different container (which you need to make sure to not destroy), or a local directory.

        See e.g. this Stack Overflow question (and answer):

        • Pietro

          Thanks for the quick answer! Another solution, just for the purposes of this guide, could be to persist data using services: if you stop and start the services related to the containers you don’t destroy the containers, and data are preserved. Bust this means to rewrite parts of the guide…

  • Hmm alright, I’m looking forward to it.

  • Great article!!!

    I am stuck at following cmd:

    $ docker build -t demo .

    Don’t run Bundler as root. Bundler can ask for sudo if it is needed, and

    installing your bundle as root will break this application for all non-root

    users on this machine.

    Could not locate Gemfile

    2015/07/18 11:05:04 The command [/bin/sh -c gem install bundler && bundle install –jobs 20 –retry 5] returned a non-zero code: 10


    I have googled it added logged in user to docker. However it didn’t unblock me. Could you help? Note: I am not using docker-machine.

    • Gino

      Any news about this problem?

  • Pingback: Running a Rails Development Environment in Docker | Dinesh Ram Kali.()

  • Thanks for the article.

    I am stuck in step 2.

    I am in Boot2Docker shell.

    When I run docker build -t demo .

    I get at the end the following:

    Step 4 : WORKDIR /app
    —> Running in 85bb73069918
    —> 1bcff2076cd5
    Removing intermediate container 85bb73069918
    Step 5 : COPY Gemfile Gemfile.lock ./
    Gemfile: no such file or directory”

    I’m on MAC OSX

    any idea why?

  • Spock

    How about not using bloated ubuntu docker container and using Debian or something smaller?

    • The actual Dockerfile used for the project uses the official Ruby containers, but you could use your own Debian based Dockerfile as well of course (or Alpine, …)

  • Brandon Conway

    I had to find for the install instructions for docker machine itself. The link you provided expects that you already have it installed.

    • Seems they moved the installation instructions to a separate page, I updated the link, thanks for letting us know!

      • Brandon Conway

        No problem, I also found that “docker-compose run -it app env” is not valid, it should be “docker-compose run app env”.

        • Ian Vaughan

          Or “docker-compose run –rm app env” as there is no need to keep the container after its been ran in this instance.

          • Denny Mueller

            thank you kind sir! That are mistakes that are horrible when you try to setup a docker enviromoment first time and use such a guide for that.

  • jmromer

    Anyone else seeing this?

    $ docker build -t demo .

    Sending build context to Docker daemon 1.378 MB

    Sending build context to Docker daemon

    Step 0 : FROM ruby:2.2

    2.2: Pulling from library/ruby

    [. . .]

    Step 9 : CMD bundle exec rails server -b

    —> Running in 214fa4c9a08f

    —> fe5cdbd79fa5

    Removing intermediate container 214fa4c9a08f

    Successfully built fe5cdbd79fa5

    $ docker run -it demo “bundle exec rake test”

    Error response from daemon: Cannot start container 918fdcd3bbd22ef38e83a666e0667bc4956e5a34a8f23ce711d10ed69145d7a0: [8] System error: exec: “bundle exec rake test”: executable file not found in $PATH

    • timtilberg

      I am as well.

    • timtilberg

      Hey, it ended up working for me when I removed quotes:

      $ docker run -it demo bundle exec rake test

  • Ke Pan

    we’ve tried this in last few months, we found it is much slower than normal ‘bundle exec rails server’ way. How do you feel?

  • A Hzg

    really good article ! Did you write another post when we want to put docker in production like digitalocean ? should we do two dockerfile for the two environemnent ? Best regars,

    • We have that article planned (as well as similar blog series for other languages) but (as always) time’s flying and I didn’t have the time to finish it yet. ;)

      As for your question, yes, I’d recommend creating a separate Dockerfile for deployment, limited to only the bare minimum of what is required to run the specific task. This will reduce attack surface as well as make the container faster to build and deploy.

      See for a blog post on creating minimal Docker containers for Ruby based applicationss!

  • Yves-Eric Martin

    Great article! But I am hitting a wall at step 2:

    `bundle install` fails if any of the gems are private, since the container does not have a way to forward authentication and authenticate with GitHub in the build phase. It is a known limitation with an issue on GitHub over a year old and still no resolution in sight:

    A few workarounds are mentioned, but none is really appealing… so I was wondering: what is Codeship’s favorite approach to deal with this problem?

  • Michael Gauthier

    Another option for your env variables is to do use the environment directive in your compose yml file

    build: .
    command: rails server -p 3000 -b ''
    - .:/app
    - "3000:3000"
    - postgres
    DATABASE_URL: 'postgres://postgres:@postgres:5432/postgres'
    image: postgres:9.4
    - "5432"

    Which then let’s you have a database.yml file that is a little more portable

    default: &default
    adapter: postgresql
    encoding: unicode
    pool: 5
    timeout: 5000

  • Vishnu Atrai

    Cool Post, helped me to setup my first docker rails registry

  • Rachit Mehrotra

    Please update me ….how should i use my local db for app ….i don’t want to create a new db container for that …..i am stuck ….searching solution for couple of days but did not find anything … would be great if anyone share any link or solution

  • Gustavo

    Great article, thanks.
    I’ve tried to build my development environemt, but I could not solve permissions problems, so I give up.
    For instance, I generate a file from the container and I need to access it a editor on the host, I cannot do that because of the permission. Is there a good way to solve this problem?

    • Filipe Giusti

      I’m also looking for a solution to that, without luck on this post. I’m sticking to `sudo chown – R user:user *` for now, or run it as if docker never existed.

  • Pingback: Deploying Your Docker Rails App -()

  • Mario López

    I’ve a theorical question. What happens if you add a gem to your Gemfile in development process. As the image is all ready builded, the gems where bundled on the docker build. How does it bundle the new gems?

    • You’d need to rebuild the image. Those changes won’t be picked up without a rebuild. But, as most layers are already cached it’s usually pretty fast.

      • Filipe Giusti

        It’s not fast! It needs to download all gems!

        • How long does installing gems need for your project? And how often do you add new Gems? Because you only need to reinstall them if you make changes, so for most parts the `docker build` should be pretty fast, even with a large `Gemfile`.

          • Filipe Giusti

            More than a minute I guess. I felt the pain because I’m starting a project, so it’s a Gemfile modification festival.

          • Hmm, yeah it’s a bit more tedious during the beginning. But once the Gemfile starts to settle, you don’t have to rebuild that often (or rebuild steps that finish quicker) and using Docker keeps your system clean while still being very easy to setup and get a project running quickly.

          • Filipe Giusti

            I agree with all the Docker benefits.

            I forgot to mention, after I wrote the initial comment I could solve the Gemfile issue using docker-compose and setting up a volume for bundle cache, this way I could do `docker-compose exec app bundle install` instead of building the image and it only takes the time to install the modified gems.

          • Abdulmujeeb Jamiu

            But this won’t commit the changes to the container image for subsequent usage, unless you explicitly do “docker commit …”

  • Gino

    I have a problem at “docker build -t demo .”:

    Sending build context to Docker daemon 100.4 kB

    Step 1 : FROM ruby:2.2.3

    —> a930a50e60f8

    Step 2 : MAINTAINER Myself

    —> Using cache

    —> 3c4ae5eefe92

    Step 3 : RUN apt-get update && apt-get install -y build-essential nodejs

    —> Using cache

    —> 65ecc91ac6be

    Step 4 : RUN mkdir -p /dev

    —> Using cache

    —> 1ce330a396b6

    Step 5 : WORKDIR /dev

    —> Using cache

    —> 9b5d130285cb

    Step 6 : COPY Gemfile Gemfile.lock ./

    —> Using cache

    —> 14c639732ae7

    Step 7 : RUN gem install bundler && bundle install –jobs 20 –retry 5

    —> Running in bac9bd66828a

    Successfully installed bundler-1.10.6

    1 gem installed

    Don’t run Bundler as root. Bundler can ask for sudo if it is needed, and installing your bundle as root will break this application for all non-root users on this machine.

    Could not locate Gemfile

    SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have ‘-rwxr-xr-x’ permissions. It is recommended to double check and reset permissions for sensitive files and directories.

    The command ‘/bin/sh -c gem install bundler && bundle install –jobs 20 –retry 5’ returned a non-zero code: 10

    Why all this?

    • Your container is missing the Gemfile. This file is required to specify which dependencies the Rails application will work with as well as which packages bundler should install.

      • timr timr

        I’m having the same problem, i posted above, i didn’t see this thread. I agree the container is missing the Gemfile and the Gemfile.lock. The question I have is why and where do they come from? I’m just starting out with rails. I am running docker on a linux box – not using docker-machine, not sure why that would be an issue. I am stopped dead at Step 6:

        • timr timr

          sorry – my bad! I didn’t realize I had to run the code before Step 1. This is where the Gemfile and Gemfile.lock are created ;-) Like all things, once figured out its obvious. Perhaps Step 0: Prepare the directory.

  • Gino

    Can you help me with a big problem about synced folders with osx and windows like vagrant synced folder. Because I have a lot of project in D:/ and I want this folder shared, not only c:/users. And also I don’t want to use VirtualBoxUI every time a start a docker-machine create. How to?

  • Oscar Ishen

    $ docker run -itP demo

    => Booting Thin

    => Rails 4.2.4 application starting in development on

    => Run `rails server -h` for more startup options

    => Ctrl-C to shutdown server

    Thin web server (v1.6.3 codename Protein Powder)

    Maximum connections set to 1024

    Listening on, CTRL+C to stop

    But when I access it says “This webpage is not available”

    • From the article you just posted a comment on:

      > We can see the container ID, the image it is based on, which command it is running, and the mapping of any exposed ports. With this information at hand, we can now open the app in our browser http://localhost:32769.

      Please don’t try to access that URL directly, this is just an example, but the article explains in detail how to get the information required to access the webserver. Just search for the above snippet and read that passage.

  • ngehani

    Thanks for the help on getting docker setup for rails – I got most of the way there except for this error. Any ideas would be greatly appreciated:

    app_1 | A server is already running. Check /app/tmp/pids/

    app_1 | => Booting WEBrick

    app_1 | => Rails 4.2.5 application starting in development on

    app_1 | => Run `rails server -h` for more startup options

    app_1 | => Ctrl-C to shutdown server

    app_1 | Exiting

    demo_app_1 exited with code 1

    • Seems like you have two webrick servers running inside the container. Could you check your Dockerfile and Docker Compose configuration to make sure it is exactly as specified in the article?

      • ngehani

        Maybe I am not interpreting your post from above correctly.
        You have this line in the dockerfile:
        CMD [“rails”, “server”, “-b”, “”] – This executes the rails server?

        You also have this line in the docker-compose.yml
        command: rails server -p 3000 -b ‘’ – This also executes the rails server?

        That’s what you have in the examples above and that’s what I have as well. Should I just have one of these and if so which one is appropriate. Am I reading this correctly?

    • Jonathan Soifer
      • John Matthew Ian Davis

        Probably, you have skipped removing the tmp directory in in the .dockerignore and the pid file that says the server is still running still exists when you copy the tmp directory.

        $ docker logs demo_app_1

        should tell you about this an pinpoint the file

    • Nithil N

      Use entrypoint to remove pid file `tmp/pids/` if exists

  • Pingback: Docker: Links, News And Resources (4) | Angel "Java" Lopez on Blog()

  • Filipe Giusti

    How do you run generators? It creates files as root and that’s a PITA.

  • John Kealy

    When I run docker -ps, it only says ” 3000/tcp “… I cannot access localhost:3000 not can I access the ip ( the output of docker-machine ls.

    • Do you have a firewall enabled on the machine running docker? Could that firewall block the connections? What OS are you running and how did you install Docker / Docker Machine?

  • timr timr

    docker build -t demo .

    Removing intermediate container 4918ac758ddd
    Step 6 : COPY Gemfile Gemfile.lock ./
    lstat Gemfile: no such file or directory

    where/when/how are these two files getting generated?

  • Milan Rawal

    I’m frequently getting “cannot find Gemfile or .bundler directory” error when doing docker-compose run. Another thing i want to know is that, I’m running docker in local virtual box machine named ‘dev’, if i do command “docker-compose up” then the containers are deployed or run in local virtual box ‘dev’.

  • Pingback: Running a Rails Development Environment in Docker | via @codeship - Geek Links()

  • Reejo Samuel

    I think you should change `docker-compose run -it app env` to `docker-compose run app env` since you are using `docker-compose`

  • Nathan Quarles

    Thanks for this great article! A question: What about apache/nginx and passenger, which are often used for production rails sites? Those would also go onto the main app container, right? So they would have to be added to the production Dockerfile as well?

    • In most cases you’d want to be able to scale the loadbalancer (Apache, nginx, …) separately from the application containers themselves.

      So you’d have a separate loadbalancer container, that uses the rails application containers as sources for the dynamic requests but requests to static files themselves.

  • brave

    Thanks a lot, very useful!

  • Aaron

    On Step 2, everything works until I run docker run -itP demo. I get an error of /bin/sh 1: [“bundle”,: not found. Not sure how to resolve this since everything else has worked properly up to this point.

    • Aaron

      I’m new to Mac so after setting up docker I was running through this tutorial using the default Mac text editor. It turns out the quotes were not the same as would be used by a code editor such as Atom so it was failing there. Once using a code editor and re-typing everything worked properly.

  • JamesAspinwall

    You are using Ubuntu, is there a way to use Alpine as supported by Docker?

    • Sure. You’d need to switch the Dockerfile to use an Alpine based image, and adapt any custom packages your application requires, but the basic workflow is the same.

      The official Ruby images on offer versions based on Alpine as well, which is a great starting point.

  • Docker On Rails

    This is a great information to get started. We’re working on a course that will cover topics such as these and more. Check out!
    Thanks for sharing (and keeping it up to date!)

  • John

    Shouldn’t `docker-compose –rm app env` be `docker-compose run app env`?

    • reali_web


    • Arman Jon Villalobos

      I can’t seem to see the `POSTGRES_PORT_5432_TCP_ADDR_*` when I run `docker-compose –rm web env`. I name my service `web` in my end. I’m using `version: ‘3’`

    • John Matthew Ian Davis

      `docker-compose run postres env` actually, since you are trying to get the address from the postgres container. – redundant with another comment I left – sorry

    • Pirun Seng

      Thank you, John! Your suggestion works for me.

  • Serguei Cambour

    When adding a postgres settings to docker-compose.yml, I get the following error:
    ERROR: yaml.scanner.ScannerError: while scanning for the next token
    found character ‘t’ that cannot start any token
    in “./docker-compose.yml”, line 8, column 1
    Any tips or ideas on how to fix that ?
    I have Docker Version 17.09.0-ce-mac35 (19611).
    Thank you.

  • Serguei Cambour

    Got it, I had to remove all the tabs symbols the settings lines start with and replace them with a space character. Weird… I’ve never had this problem with a RoR yaml configuration files, may be docker-composer uses a different parser …

  • dorelly2

    Very bad article. Nothing to add.

    • I’m sorry you feel that way. If you could have any specific questions, or areas where we should improve the article, let me know.

  • Vitali Prodan

    Where does comes from?

  • Serguei Cambour

    Even if the article was last updated on 2018-02-27, some points seem to be outdated. Besides Ruby version (actually 2.5.1, but this has no impact), there is another one: docker-compose –rm app env. This one fails on macOS, Docker version 18.03.1-ce-mac65 (24312) as follows: Define and run multi-container applications with Docker.

    docker-compose [-f …] [options] [COMMAND] [ARGS…]
    docker-compose -h|–help
    other available commands.It seems like –rm does not exist anymore.

    • John Matthew Ian Davis

      The correct command is:
      docker-compose run –rm app env

      • John Matthew Ian Davis

        Excuse me:
        docker-compose run –rm postgres env

        The previous gives you the environment for the rails container. You want the parameters from the *db* to give to the rails container.

        • John Matthew Ian Davis

          the –rm means remove the container generated after running the one-time command.

  • JohnDSmall

    In your docker-compose.yml you’re mapping the /app directory to the local . directory

    – .:/app

    But if I do that the the container is no longer isolated, which surely defeats the point of Docker. I can’t copy the image to another machine and expect it to run. Also I can’t have many containers running from the same image because they’ll all be trying to write to the same directory.

    So I’m mystified why you’re doing this unless it’s to make it easier to edit the files in the app. But then why Dockerise the app?

    • The `docker-compose.yml` file is only setup for local testing and overrides the `/app` directory inside the Docker image with the contents of your local project root. (The main `Dockerfile` includes a `COPY . ./`, which adds the contents of that directory to the image whenever it is built.) The reason why it is configured this way is so you don’t have to rebuild the Docker image with each change.

      If you build the image (via `docker build`) you’ll still get an image that you can push to e.g. Docker Hub (or another registry) and use for other purposes. That said, the goal of this article was not to prepare a Rails application for deployment via Docker, but to make an easy to share development environment.

      Why you’d want to use Docker in your development environment? For me personally the main reasons are that I don’t want to install a bunch of development dependencies locally. I don’t want to run PostgreSQL, MySQL, various Ruby versions locally. I want to have those in separate environments that I can easily clean up and discard once I no longer need them.

      Plus, as mentioned above, this is an easy way to share a complete development environment with the rest of your team and make sure that everybody is using with the same versions. (E.g. everybody is using the same version or Ruby, PostgreSQL, Redis, …). It also allows somebody new to this specific application to clone the repository and run a single command (`docker-compose up…`) to get started. There is no “I need to install this version of Ruby, plus I’m currently on an older version of PostgreSQL, and I don’t have the necessary dev package for obscure library Y installed that is required by one of the Gems.

  • Pirun Seng

    Hi There, thanks for this article. By the way, I’m stuck on Step 2 as I need to modify the Docker file with these:

    FROM ubuntu:16.04
    FROM ruby:2.3.3

    And I’m getting an error as:

    E: Failed to fetch 403 Forbidden [IP: 80]

    E: Aborting install.
    The command ‘/bin/sh -c apt-get clean && apt-get update && apt-get install -y –fix-missing build-essential nodejs’ returned a non-zero code: 100

    Really appreciate for your help!

  • Richard McSharry

    This article is so incredibly valuable I just had to share it on LinkedIn:

  • Pingback: ruby-on-rails - Ventana acoplable Componer + Rails: mejores prácticas para migrar?()