I tried to build an environment using Docker (beginner)

Overview

I tried to build a development environment for Ruby on Rails using Docker. By using Docker, you can build a development environment regardless of the local environment, and you can migrate from the development environment to the production environment without changing the settings, so it is used in many development sites. This is the final setting I created after studying Docker on my own.

version

Ruby 2.6.3 Ruby on Rails 5.2.0 Docker 19.03.13 docker compose 1.27.4 MySQL 5.7 Nginx 1.15.8

Premise

Directory structure

Directory structure


./myapp
├── containers
│   └── nginx
│       ├── Dockerfile
│       └── nginx.conf
├── .env
├── docker-compose.yml
├── Dockerfile
├── Gemfile
└── Gemfile.lock

Details of each directory and file

** Dockerfile for Rails **

Dockerfile


FROM ruby:2.6.3

RUN apt-get update\
  && apt-get install -y --no-install-recommends\
  libpq-dev\
  nodejs\
  vim\
  mariadb-client\
  build-essential\
  && apt-get clean\
  && rm -rf /var/lib/apt/list/*

RUN mkdir /myproject
WORKDIR /myproject

COPY Gemfile /myproject/Gemfile
COPY Gemfile.lock /myproject/Gemfile.lock

RUN gem install bundler
RUN bundle install

COPY . /myproject

RUN mkdir -p tmp/sockets
RUN mkdir -p tmp/pids

Gemfile

Gemfile


source 'https://rubygems.org'

gem 'rails', '5.2.0'

Gemfile.lock The contents are empty and OK

** Dockerfile for Nginx **

Dockerfile


FROM nginx:1.15.8

RUN rm -f /etc/nginx/conf.d/*

ADD nginx.conf /etc/nginx/conf.d/myproject.conf

CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

** Nginx.conf file **

nginx.conf


upstream myproject {
  server unix:///myproject/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name IP address[or localhost];

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;
  
  root /myproject/public;

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @myproject;
  keepalive_timeout 5;

  location @myproject {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://myproject;
  }
}

** .env file **

.env


MYSQL_ROOT_PASSWORD=password
MYSQL_USER=username
MYSQL_PASSWORD=password
MYSQL_DATABASE=docker_database

** docker-compose.yml file **

docker-compose.yml


version: '3'

services:
  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    env_file:
      - ./.env
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - "4306:3306"

  app:
    build: .
    env_file:
      - ./.env
    command: bundle exec puma -C config/puma.rb
    init: true
    volumes:
      - .:/myproject
      - public-data:/myproject/public
      - tmp-data:/myproject/tmp
      - log-data:/myproject/log
    depends_on:
      - db

  web:
    build:
      context: containers/nginx
    init: true
    volumes:
      - public-data:/myproject/public
      - tmp-data:/myproject/tmp
    ports:
      - 80:80
    depends_on:
      - app

volumes:
  mysql-data:
  public-data:
  tmp-data:
  log-data:

Rails application settings

First, create a Rails application with rails new.

terminal


$ docker-compose run --rm app bundle exec rails new . --force --database=mysql --skip-bundle

Then edit the puma file in the config directory.

puma.rb


threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

app_root = File.expand_path("../..", __FILE__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true

Edit database.yml.

database.yml


default: &default
  adapter: mysql2
  charset: utf8
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("MYSQL_USER") { 'root' } %>
  password: <%= ENV.fetch("MYSQL_PASSWORD") { 'password' } %>
  host: db

development:
  <<: *default
  database: docker_database

test:
  <<: *default
  database: myproject_test

production:
  <<: *default
  database: myproject_production
  username: myproject
  password: <%= ENV['MYPROJECT_DATABASE_PASSWORD'] %>

Start container

When you're ready, start the container.

terminal


$ docker-compose build
When the build is complete
$ docker-compose up

If you access localhost and the Rails page is launched, you're done.

When building an environment for an existing Rails application with docker

Add the following directories and files to the application folder. (File settings are the same as when creating from scratch.)

Directory structure


./myapp
├── containers
│   └── nginx
│       ├── Dockerfile
│       └── nginx.conf
│
│ Other files
│
├── .env
├── docker-compose.yml
└── Dockerfile

Then build. You don't need to run the rails new command because you already have the application. The database needs to be migrated once, so migrate it after the build.

terminal


$ docker-compose build
When the build is complete
$ docker-compose up -d
$ docker-compose exec app rails db:migrate

With the above, if you access localhost, you can install docker in your existing application.

Supplement

I was still lacking in study, and I had a hard time getting an error on the way. Each time, I searched online and solved it.

Addictive error

On the reference page

python


$ docker-compose run --rm app rails new . --force --database=mysql --skip-bundle

It was, but

python


$ docker-compose run --rm app bundle exec rails new . --force --database=mysql --skip-bundle

I was able to install the Rails files.

$ docker-compose build
...
Bundler could not find compatible versions for gem "sprockets":
  In snapshot (Gemfile.lock):
    sprockets (= 4.0.2)

  In Gemfile:
    sass-rails (~> 5.1) x86_64-linux was resolved to 5.1.0, which depends on
      sprockets (>= 2.8, < 4.0)

    rails (~> 5.2.0) x86_64-linux was resolved to 5.2.0, which depends on
sprockets-rails (>= 2.0.0) x86_64-linux was resolved to 3.2.2, which
depends on
        sprockets (>= 3.0.0)

Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
ERROR: Service 'app' failed to build : The command '/bin/sh -c bundle install' returned a non-zero code: 6

I'm told to do a bundle update, so I'll do a bundle update.

python


$ docker-compose run app bundle update
afterwards
$ docker-compose build

Summary

I managed to build an environment with docker, but I still struggled due to lack of study. When I first started using docker, I made an existing application docker. After that, I tried to install docker from building a new environment, but I stumbled many times. I would like to study the detailed settings again and give explanations for each one someday.

References

Docker + Rails + Puma + Nginx + MySQL # Error resolution rails new can't run bundle update will rebuild your snapshot from scratch, using only the gems in your Gemfile, which may resolve the conflict.

Recommended Posts

I tried to build an environment using Docker (beginner)
I tried to build the environment little by little using docker
I tried to build the environment of WSL2 + Docker + VSCode
I tried to build the environment of PlantUML Server with Docker
I tried to build an http2 development environment with Eclipse + Tomcat
I installed WSL2 without using Microsoft Store and tried to build an environment where Docker can be used
I tried to build a Firebase application development environment with Docker in 2020
01. I tried to build an environment with SpringBoot + IntelliJ + MySQL (MyBatis) (Windows10)
[Road _node.js_1-1] Road to build Node.js Express MySQL environment using Docker
Rails6 I tried to introduce Docker to an existing application
Try to build a Java development environment using Docker
When I tried to build an environment of PHP7.4 + Apache + MySQL with Docker, I got stuck [Windows & Mac]
How to build CloudStack using Docker
I want to build Java Applet without using an IDE
I tried to create React.js × TypeScript × Material-UI on docker environment
I tried to create a padrino development environment with Docker
[Docker] Building an environment to use Hugo
I tried using Scalar DL with Docker
I tried to integrate Docker and Maven / Netbean nicely using Jib
Build an authentication proxy server using Docker
I tried to build a simple application using Dockder + Rails Scaffold
I tried to make it an arbitrary URL using routing nesting
I tried to build an API server with Go (Echo) x MySQL x Docker x Clean Architecture
What is Docker? I tried to summarize
I tried to build Ruby 3.0.0 from source
Build an Ultra96v2 development environment on Docker 1
How to build Rails 6 environment with Docker
After learning Progate, I tried to make an SNS application using Rails in the local environment
Build an environment of "API development + API verification using Swagger UI" with Docker
I tried to make an automatic backup with pleasanter + PostgreSQL + SSL + docker
I tried migrating the portfolio created on Vagrant to the Docker development environment
I tried to verify AdoptOpenJDK 11 (11.0.2) with Docker image
I tried to build Micra mackerel in 1 hour!
I tried installing docker on an EC2 instance
I tried to develop an application in 2 languages
[First team development ②] Build an environment with Docker
I tried to implement a server using Netty
I tried using Gson
I tried using TestNG
I tried using Galasa
[App development 1] [Node.js express Docker] Build an environment for Node.js Express MongoDB (mongoose) using Docker [December 2020]
[Error resolution] Occurs when trying to build an environment for spring with docker
How to build docker environment with Gradle for intelliJ
I tried to summarize the state transition of docker
Build an environment of Ruby2.7.x + Rails6.0.x + MySQL8.0.x with Docker
I tried to operate SQS using AWS Java SDK
I tried using Docker Desktop for Windows on Windows 10 Home
I tried using an extended for statement in Java
[2021] Build a Docker + Vagrant environment for using React / TypeScript
[Rails] How to connect to an external API using HTTP Client (I tried connecting to Qiita API)
I got an error when trying to install sbt to build a Scala development environment
I tried node-jt400 (Environment construction)
I tried using azure cloud-init
I tried Rails beginner [Chapter 1]
I tried the Docker tutorial!
I tried using Apache Wicket
Build docker environment with WSL
I tried using Java REPL
I tried Rails beginner [Chapter 2]
I tried BIND with Docker
I tried to verify yum-cron