环境

  • ubuntu 16.04
  • rails: 5.1.1
  • ruby: 2.3.3
  • docker: 17.03.1-ce
  • docker-compose: 1.11.2
  • sidekiq: 5.0
  • mysql: 5.7
  • redis: 3.2.9

最近终于有机会尝试一下基于Docker容器化的Rails开发环境塔建,记录一下过程。

准备

首先要到 https://www.docker.com/community-edition 下载 Docker for Mac 并安装。

创建项目目录:

mkdir -p ~/workspace/app
cd ~/workspace/app

创建 GemfileGemfile.lock 文件:

touch Gemfile
touch Gemfile.lock

Gemfile文件内容:

source 'https://rubygems.org'
gem 'rails', '~> 5.1.1'

创建 Dockerfile 文件:

此文件基于ruby的镜像(Ubuntu系统)创建,并安装Rails环境需要的依赖。 并将mysql数据文件及bundle文件统一放置在指定目录(后面会做成数据卷存放)

FROM ruby:2.3.3
RUN apt-get update -yqq \
  && apt-get install -yqq --no-install-recommends \
    apt-utils \
    build-essential \
    nodejs \
    tzdata \
    libmysqlclient-dev \
    zlib1g-dev \
    libyaml-dev \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*

WORKDIR /usr/app/web
RUN mkdir -p /usr/app/mysql
RUN mkdir -p /usr/app/bundle
ENV BUNDLE_PATH=/usr/app/bundle

RUN gem install bundler
RUN bundle config --global silence_root_warning 1
ADD Gemfile /usr/app/web/Gemfile
ADD Gemfile /usr/app/web/Gemfile.lock
RUN bundle install

创建 docker-compose.yml 文件:

此文件用于方便地管理多个容器。

version: '2'

# 创建mysql/redis/bundle的数据卷
volumes:
  mysql-data: {}
  redis-data: {}
  bundle-data: {}

services:
  web:
    # 指定构建目录
    build: .
    # 指定环境变量文件
    env_file:
      - .env
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    # 映射项目文件目录,实现容器外的项目文件编辑开发
    # 映射bundle的数据卷,重新build容器时不用重新下载所有Gem
    volumes:
      - .:/usr/app/web
      - bundle-data:/usr/app/bundle
    # 将容器的端口映射到宿主机
    ports:
      - 3000:3000
    # 连接指定其他容器,用于在Rails的配置文件中指定数据库容器的Host
    links:
      - db:db
      - redis:redis
    # 容器间的依赖关系,Docker会根据依赖关系,顺序启动容器
    depends_on:
      - db
      - redis

  sidekiq:
    build: .
    env_file:
      - .env
    command: bundle exec sidekiq -C config/sidekiq.yml
    volumes:
      - .:/usr/app/web
    links:
      - redis:redis
    depends_on:
      - redis

  db:
    image: mysql:5.7
    # 将mysql的数据挂载到数据卷上,防止数据丢失
    volumes:
      - mysql-data:/var/lib/mysql
    env_file:
      - .env
    # 将mysql的端口隐射到宿主机,用于客户端连接管理
    ports:
      - 3307:3306
    command: ['mysqld', '--character-set-server=utf8']

  redis:
    image: redis
    # 将redis的端口隐射到宿主机,用于客户端连接管理
    # 因为宿主机已经存在redis,所以映射出来的端口改为6380
    ports:
      - 6380:6379
    volumes:
      - redis-data:/data

创建环境变量文件 .env:

REDIS_URL=redis://redis:6379/0
MYSQL_ROOT_PASSWORD=test
TZ=Asia/Shanghai

创建 .dockerignore 文件,用于忽略一些不必要的文件,节省容器空间,当然项目整个目录映射出来后,这个文件就不大需要了:

/tmp/*
/log/*.log

/vendor/bundle

.bash_history
.byebug_hist
.pry_history

docker-compose.yml
first_time_setup.sh

.git*

创建项目及重建镜像

使用如下命令在当前目录(Dockerfile所在目录)创建Rails项目,因为使用run命令运行容器时,每次都会创建容器,而这次运行只是为了利用容器环境来创建项目,所以要加--rm参数, 在创建完项目后删除容器。

docker-compose run --rm web rails new . --force --database=mysql --skip-action-cable

构建镜像:

docker-compose build

使用

项目服务运行前,需要修改数据库配置文件 database.yml:

# 注意这里的host对应docker-compose.yml内容器配置的links设置
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: google
  host: db

development:
  <<: *default
  database: web_development

创建数据库:

docker-compose run --rm web rails db:create

创建redis连接及sidekiq配置 config/initializers/redis.rb:

redis_url = ENV.fetch("REDIS_URL"){ "redis://127.0.0.1/6379/0" }
Sidekiq.configure_server do |config|
  config.redis = { namespace: 'sidekiq', url: redis_url }
end
Sidekiq.configure_client do |config|
  config.redis = { namespace: 'sidekiq', url: redis_url }
end

添加需要的Gems 到 Gemfile:

gem 'redis', '~> 3.3'
gem 'redis-rails', '~> 5.0'
gem 'sidekiq', '~> 5.0'

安装Gems:

docker-compose run --rm web bundle install
# 并重新构建镜像
docker-compose build

启动容器:

docker-compose up

控制台输出:

web_1      | => Booting Puma
web_1      | => Rails 5.1.1 application starting in development on http://0.0.0.0:3000
web_1      | => Run `rails server -h` for more startup options
web_1      | Puma starting in single mode...
web_1      | * Version 3.8.2 (ruby 2.3.3-p222), codename: Sassy Salamander
web_1      | * Min threads: 5, max threads: 5
web_1      | * Environment: development
web_1      | * Listening on tcp://0.0.0.0:3000
web_1      | Use Ctrl-C to stop

至次可以通过宿主机浏览器打开 http://localhost:3000 访问Rails默认页。

其他常用操作

# 创建模型
docker-compose run --rm web rails g model User name:string
# 应用迁移
docker-compose run --rm web rails db:migrate
# 创建控制器
docker-compose run --rm web rails g controller users
# 进入console
docker-compose run --rm web rails console
# 进入web容器命令行
docker-compose run --rm web bash

# 停止所有容器
docker stop $(docker ps -a -q)
# 删除所有容器
docker rm $(docker ps -a -q)
# 删除Docker多余空间占用(慎用)
docker system prune

参考