Rails & Docker
Publié il y a presque 3 ans~3 min
Being a developer often means working as a team :juggling::juggling::juggling:. But who has never known THE famous installation that takes a day (or more...) because of environmental concerns or dependencies? Fortunately, Docker is here! Thanks to its containers logic, it allows you to encapsulate applications with their dependencies, thus freeing us from project portability concerns.
Based on a standard Ruby On Rails project, we are going to set up the various elements necessary for its dockerization.
Prerequisites
- Docker and Docker Compose
- A Ruby On Rails project (≥ 5.1) using Webpacker and PostgreSQL (≥ 10)
A demonstration project has been created for this article, so do not hesitate to refer to it for more details (scripts, ...)!
Dockerfile
Any Docker project is defined by an original image, which will then be used as a basis for building the various containers (application, database, ...). To do this, all you have to do is create a file simply named Dockerfile
at the root of our project:
1FROM ruby:2.5.5-alpine23ARG PRECOMPILEASSETS4ARG RAILS_ENV56ENV SECRET_KEY_BASE foo7ENV RAILS_ENV ${RAILS_ENV}8ENV RAILS_SERVE_STATIC_FILES true910RUN apk add --update --no-cache \11 build-base \12 git \13 postgresql-dev \14 postgresql-client \15 imagemagick \16 nodejs-current \17 yarn \18 python2 \19 tzdata \20 file2122RUN gem install bundler23# Install gems24RUN mkdir /gems25WORKDIR /gems26COPY Gemfile .27COPY Gemfile.lock .28RUN bundle install -j4 --retry 3 \29 # Remove unneeded files (cached *.gem, *.o, *.c)30 && rm -rf /usr/local/bundle/cache/*.gem \31 && find /usr/local/bundle/gems/ -name "*.c" -delete \32 && find /usr/local/bundle/gems/ -name "*.o" -delete3334ARG INSTALL_PATH=/railsondocker35ENV INSTALL_PATH $INSTALL_PATH3637WORKDIR $INSTALL_PATH38COPY . .3940# Precompile assets (or not)41RUN docker/potential_asset_precompile.sh $PRECOMPILEASSETS4243CMD ["docker/startup.sh"]
The starting point for our file is a Docker image for Ruby. A so-called "alpine" version is used here, that's to say embedding the minimum required to optimize the weight of the final generated image.
We then install the various necessary libraries (postgresql, nodejs, ...) and the gems declared in the Gemfile
(with a little cleaning at the end of the task, again to optimize the final weight).
Finally, we precompile the assets (if necessary) before launching the global command declared via the CMD
instruction, which will take care of launching the server (Puma) after having prepared the database (cf. startup.sh
script).
Note the use of variables that will allow us to build a specific image depending on the environment (development, production, ...). These variables will be defined in each docker-compose.yml
file.
Docker Compose
Our general constructor being now ready, all that remains is to define the different containers of our application, with any variations depending on the environment.
In development mode, Rails and Webpacker are separated, in order to improve the responsiveness of the whole. The docker-compose.yml
file is quite simple to understand, its syntax remaining quite clear:
1version: '3.0'2services:3 db:4 image: postgres:11-alpine5 ports:6 - 5433:54327 environment:8 POSTGRES_PASSWORD: postgres910 webpacker:11 image: railsondocker_development12 command: ["./docker/start_webpack_dev.sh"]13 environment:14 - NODE_ENV=development15 - RAILS_ENV=development16 - WEBPACKER_DEV_SERVER_HOST=0.0.0.017 volumes:18 - .:/railsondocker:cached19 ports:20 - 3035:30352122 app:23 image: railsondocker_development24 build:25 context: .26 args:27 - PRECOMPILEASSETS=NO28 environment:29 - RAILS_ENV=development30 links:31 - db32 - webpacker33 ports:34 - 3000:300035 volumes:36 - .:/railsondocker:cached
Our three containers are therefore linked to images (from the Dockerfile
, with the exception of PostgreSQL, for which we use an "alpine" image). They are assigned ports, and possibly commands to be executed at launch.
In some cases, we will define arguments or environment variables, useful for the Dockerfile
.
Finally the links between services are declared in the app
container, in the links
part.
Rails configuration
Now that the Docker part is set up, we need to make some adjustments in the configuration of our Ruby On Rails project, in particular to take into account the variables defined in the Compose files:
config/database.yml
, forhost
andusername
/password
config/webpacker.yml
, for Webpacker serverhost
config/environments/*.rb
, to report the variables defined in thedocker-compose.yml
(optional)
🎉
Et voilà ! Now all that remains is to run the docker-compose build
command to build our Docker image, then the docker-compose up
command to launch our project on localhost: 3000
! Subsequently, we can add new containers (or services): mail server, ... 🙂