Goal Hello. There were many articles about building a Docker environment for Nuxt.js and Rails, but since there was no article about Next.js, it is a record of building an environment by trial and error. I don't often post to Qiita, so I refer to @ at-946 for the article title and article structure.
--Reference article "Nuxt.js + Rails (API) on Docker Hello World!"
The file structure to be prepared is as follows.
DirectoryStructure
/
|--front/
| |--Dockerfile
|--back/
| |--Dockerfile
| |--Gemfile
| |--Gemfile.lock #Empty file
|--docker-compose.yml
front/Dockerfile
From node:14-alpine
WORKDIR /usr/src/app
back/Dockerfile
FROM ruby:2.5
ENV LANG=C.UTF-8 \
TZ=Asia/Tokyo
WORKDIR /app
RUN apt-get update -qq && \
apt-get install -y nodejs default-mysql-client
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
back/Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6.0.3', '>= 6.0.3.2'
docker-compose.yml
version: "3"
services:
db:
container_name: database
image: mysql:5.7
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sample
MYSQL_USER: root
MYSQL_PASSWORD: password
TZ: Asia/Tokyo
ports:
- 3308:3306
volumes:
- ./database/my.cnf:/etc/mysql/conf.d/my.cnf
- ./database/data:/var/lib/mysql
- ./database/sql:/docker-entrypoint-initdb.d
api:
container_name: back
tty: true
depends_on:
- db
build:
context: back/
dockerfile: Dockerfile
ports:
- 3000:3000
volumes:
- ./back:/app
command: rails server -b 0.0.0.0
front:
build:
context: front/
dockerfile: Dockerfile
container_name: web
volumes:
- ./front/app:/usr/src/app
command: 'yarn dev'
ports:
- "4001:3000"
Build the above files once they are ready.
$ docker-compose build
$ docker-compose run --rm front yarn create next-app .
After waiting for a while, I think the Next.js app will be generated (should). Let's start it right away.
$ docker-compose up
Try accessing localhost: 4001
. If all goes well, you should see Welcome to Next.js!
.
Next is the Rails environment construction. RDB adopts MySQL
. Rails puts it in API mode
.
$ docker-compose run --rm api bundle exec rails new . --api -d mysql
Gemfile conflicts on the way, so be sure to overwrite it.
Overwrite /app/Gemfile? (enter "h" for help) [Ynaqdhm] Y
After creating the Rails app, let's match the database settings with the Mysql settings created with docker-compose.yml
.
back/config/database.yml
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
# gem 'mysql2'
#
# And be sure to use new-style password hashing:
# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
host: database
development:
<<: *default
database: sample
# 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.
test:
<<: *default
database: app_test
# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%= ENV['DATABASE_URL'] %>
#
production:
<<: *default
database: app_production
username: app
password: <%= ENV['APP_DATABASE_PASSWORD'] %>
Let's start it.
$ docker-compose up --build
Try accessing localhost: 3000
. It is OK if the following screen is displayed.
Let's create an API on the Rails side so that it can work with the Next.js side.
$ docker-compose run --rm api bundle exec rails g scaffold post title:string
I think I was able to do it smoothly. We will create a table, so let's migrate
.
$ docker-compose run --rm api bundle exec rake db:migrate
I can't return JSON because there is no data when I create the table. I am troubled···. Let's create test data.
Rails has a handy feature called seed
that captures the initial data.
back/db/seeds.rb
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
#
# Examples:
#
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
# Character.create(name: 'Luke', movie: movies.first)
Post.create!(
[
{
title: 'There is a store near the office that sells baked sweet potatoes'
},
{
title: 'There seems to be a front engineer who distributes roasted sweet potatoes'
}
]
)
Oops, I've been angry with the test data. Please don't look at it. Now let's get the test data into the table.
$ docker-compose run --rm api bundle exec rake db:seed
Let's check it.
$ docker-compose up
Let's access localhost: 3000/posts
. You can see that kind of data. It's a success.
Now, let's finally display the data acquired by the API on the Next.js side.
I rewrote front/app/pages/index.js
as follows.
It simply displays the data acquired by the API.
front/app/pages/index.js
export default function Home(props) {
return (
<div>
<h1>List of POST</h1>
{props.posts.map((post) =>
<p>{ post.title }</p>
)}
</div>
)
}
export async function getStaticProps() {
const response = await fetch("http://localhost:3000/posts", {method: "GET"});
const json = await response.json();
return {
props: {
posts: json
},
};
}
Let's access http: // localhost: 4001
... that? ?? ?? Is it the curse of our front engineer? ??
localhost: 3000
doesn't seem to work on the Next.js side.
Let's specify the host in the environment settings. (I'm not sure why)
Matched to the container name in docker-compose.yml
.
back/config/environments/development.rb
Rails.application.configure do
...
config.hosts << "api"
end
Next, change the API URL on the Next.js side.
front/app/pages/index.js
export async function getStaticProps() {
const response = await fetch("http://api:3000/posts", {method: "GET"});
・ ・ ・
}
Let's start docker again.
$ docker-compose up
Oh, it seems that it was finally displayed.
I'm tired of writing an article after a long time.
Recommended Posts