An Interest In:
Web News this Week
- April 26, 2024
- April 25, 2024
- April 24, 2024
- April 23, 2024
- April 22, 2024
- April 21, 2024
- April 20, 2024
Deploy Rails 7 with Docker and Nginx
The easiest solution to deploy a Rails application is something like Heroku or Hatchbox or DigitalOcean Apps. But for some small projects I like to use my existing VPS.
I assume you have a VPS with Ubuntu 20.04 and Docker and Nginx installed.
If you use DigitalOcean you can select the Docker image in the marketplace and add Nginx to it.
New Rails 7 app
Lets create a new Rails project with PostgreSQL, esbuild and Tailwind on your local machine:
rails new demo -d postgresql --edge -j esbuild --css tailwind
Adjust you config/database.yml with the settings for your database.
Scaffold a simple table:
bin/rails g scaffold Book name:string
Then create your database and tables:
bin/rails db:createbin/rails db:migrate
You can create a root path in routes.rb:
root "books#index"
Now you can start the website with:
bin/dev
Docker
Let's go to the VPS. I transfer my code with Github.
For large projects you would probably use CI, but this is just a small project.
I prefer to create a small shell script to do the build steps and start rails.
This is the content of bin/prod
:
#!/usr/bin/env bashexport RAILS_ENV=productionbundle installyarn installyarn buildyarn build:cssbin/rails assets:precompilebin/rails server -b 0.0.0.0
Let's make it executable with: chmod a+x bin/prod
Now create a Dockerfile:
FROM ruby:3RUN apt-get update -qq && apt-get install -y nodejs npm postgresql-clientRUN npm install -g yarnRUN gem update --system# use a global path instead of vendorENV GEM_HOME="/usr/local/bundle"ENV BUNDLE_PATH="$GEM_HOME"ENV BUNDLE_SILENCE_ROOT_WARNING=1ENV BUNDLE_APP_CONFIG="$GEM_HOME"ENV PATH="$GEM_HOME/bin:$BUNDLE_PATH/gems/bin:${PATH}"# make 'docker logs' workENV RAILS_LOG_TO_STDOUT=true# copy the sourceWORKDIR /appCOPY . /appRUN rm -f tmp/pids/server.pidRUN bundle install# build and startCMD ["bin/prod"]
The master.key file is not in git for safety.
There are several solutions for this, but I just recreate the file on the server:
echo "30acf9tralalalalala7af75eb7" > config/master.key
Now it's time to create the docker image.
Run this inside the root folder of the demo project:
docker build -t demo:0.0.1 .
You should now see the image with docker images
.
Lets run it:
docker run -d -p 3001:3000 --name demo --env RAILS_ENV=production -v ~/demo:/app demo:0.0.1
The docker container is exposing port 3000, but I map that to 3001 since I already have an other website running on port 3000.
You should probably have a seperate Postgres server, but I also run that inside a Docker.
To allow access to this container I create a seperate network and add the two containers in it.
In database.yml you can than use postgres_container as host.
docker network create demo_networkdocker network connect demo_network demodocker network connect demo_network postgres_container
To create the database and tables:
docker exec demo bin/rails db:createdocker exec demo bin/rails db:migrate
In case of errors you can use docker logs demo
to find the error.
Nginx
I use Nginx as a proxy to the different Rails projects and to load the assets directly.
To create a new configuration:
sudo vi /etc/nginx/sites-available/demo
And this is the content: (you need to change the domain and paths)
upstream demo { server localhost:3001;}server { server_name demo.example.org; root /home/user/demo/public; access_log /home/user/demo/log/nginx.access.log; error_log /home/user/demo/log/nginx.error.log info; location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; } try_files $uri/index.html $uri @demo; location @demo { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Ssl on; # Optional proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-Host $host; proxy_redirect off; proxy_pass http://demo; } error_page 500 502 503 504 /500.html; client_max_body_size 100M; keepalive_timeout 10;}
Enable it:
sudo ln -s /etc/nginx/sites-available/demo /etc/nginx/sites-enabled/demo
Test the configuration:
sudo nginx -t
And restart Nginx:
sudo systemctl restart nginx
You should now have a working website.
It's a good idea to add Let's Encrypt with the certbot tool.
This is explained here.
Original Link: https://dev.to/roelandmoors/deploy-rails-7-with-docker-and-nginx-b11
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To