It has always been easier to supply the necessary tools locally. If you need to have multiple versions, then rvm or nvm solve the problem. Then came Docker. Until this year, I had successfully managed to avoid it. On projects where the guys worked with Docker, I instead installed everything locally. But, I thought that enough fighting and it's time to try to live with the idea of "docker for everything". It's simply time to admit either i work using Docker or i don't work at all.
Well I don't have ruby installed locally. And I need to generate a new Rails application or experiment in IRB.
The first thing I did was look at the official Rails image. It turned out to be deprecated, and the authors suggested Ruby as a replacement.Using Ruby image, I was unable to generate a Rails application, so Imade my own Docker image.
FROM debian:bullseye
WORKDIR /app
ARG ruby_version=2.7.1
ARG PG_MAJOR=13
ARG NODE_MAJOR=14
# Installing general packages
RUN apt update \
&& apt upgrade -y \
&& apt install libpq-dev postgresql-client-$PG_MAJOR gnupg2 git wget curl vim build-essential libssl-dev zlib1g-dev libyaml-dev libffi-dev -y
# Installing rbenv and ruby
RUN apt install rbenv -y \
&& echo 'eval "$(rbenv init -)"' >> ~/.bashrc \
&& rbenv install $ruby_version \
&& rbenv global $ruby_version \
&& eval "$(rbenv init -)" \
&& gem install rails
#Installing node and yarn
RUN curl -sL https://deb.nodesource.com/setup_$NODE_MAJOR.x | bash - \
&& apt install nodejs \
&& npm i -g yarn
ENV PATH /root/.rbenv/versions/$ruby_version/bin/:/root/.rbenv/shims:$PATH
The following command will generate a new Rails application in the current folder and install required gems in the gems folder. As you know, a container cannot change its content after it has been built.Therefore, all application files and gems will be stored on the host machine.
docker run --rm -v /$(pwd):/app rukomoynikov/rails rails new .
Launching the application is not much more difficult. But, in a simple form, it will only work if you use the sqlite database.
docker run --rm -it -p 3000:3000 -v /$(pwd):/app rukomoynikov/rails rails s -b 0.0.0.0
Running IRB. Or you can enter console and run ruby files from local machine.
docker run --rm -it -p 3000:3000 -v /$(pwd):/app rukomoynikov/rails bash
Above you saw an example of basic Rails application used SQLite. In order to use Postgresql and Webpacker you need something more complicated than simple Dockerfile. You need docker-compose. There you will be able to separate application into a ruby service, and the client service.
Here is example of docker-compose.yml
services:
web:
image: rukomoynikov/rails:2.7.1
volumes:
- ./:/app
- rails_cache:/app/tmp/cache
- bundle:/usr/local/bundle
ports:
- 3000:3000
tmpfs:
- /tmp
- /app/tmp/pids
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
command: bundle exec rails server -b 0.0.0.0
client:
image: rukomoynikov/rails:2.7.1
command: yarn run build -w
ports:
- '3035:3035'
volumes:
- ./:/app:cached
- bundle:/usr/local/bundle
- node_modules:/app/node_modules
- packs:/app/public/packs
environment:
WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
postgres:
image: postgres:13
volumes:
- postgres:/var/lib/postgresql/data
environment:
PSQL_HISTFILE: /root/log/.psql_history
POSTGRES_PASSWORD: postgres
ports:
- 5432
healthcheck:
test: pg_isready -U postgres -h 127.0.0.1
interval: 5s
redis:
image: redis:3.2-alpine
volumes:
- redis:/data
ports:
- 6379
healthcheck:
test: redis-cli ping
interval: 1s
timeout: 3s
retries: 30
volumes:
postgres:
redis:
bundle:
rails_cache:
node_modules:
packs: