Docker」タグアーカイブ

DockerでRailsの開発環境を構築する

前提

以下の環境でDockerを使用する。またDockerHubのアカウントについては既に準備しているものとする。

要素 バージョン
debian 8.6
docker 1.13.0

概要

Mac上に立ち上げたDebian内でDockerを用いてRuby on railsの開発環境を構築する。railsについても学習用の環境にすぎないので、細かいバージョンなどはあまり気にしない方針。

構築にあたっては、rails環境用のDockerイメージをDockerHubから探すだけでも済むが、今回はDocker及び環境構築の学習を含めて以下の手順で構築する。

  1. DockerHubからUbuntuのベースイメージをpull
  2. コンテナを作成し、コンテナ内で環境構築(=Dockerfileは使わない)
  3. コンテナをコミット
  4. 作成したイメージをDockerHubにpush

元となるDockerイメージを取得

今回は使い慣れているUbuntuを用いてrails環境を構築するので、DockerHubからubuntuのイメージをpullする。

$ docker pull ubuntu

イメージが手に入ったら、コンテナを生成してアクセスする。以降の項ではコンテナ内で作業を行う。後々動作確認でコンテナにWebブラウザでアクセスするので、ポートフォワーディングの設定(8081→3000)も指定しておく

$ docker run -it -p 8081:3000 -name my_ubuntu ubuntu

Railsの環境構築

開発環境の前準備

まずはapt-getを更新

$ apt-get update
$ apt-get upgrade

日本語が使えない状態だったので日本語化作業

$ apt-get install language-pack-ja
$ update-locale LANG=ja_JP.UTF-8
$ echo "export LANG=ja_JP.UTF-8" >> ~/.bashrc

開発に必要になる基本的なツールをインストール

$ apt-get install vim git git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libpq-dev libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev aptitude

後々必要になりそうなのでnodejsも適当に入れておく

$ curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
$ apt-get install -y nodejs

Rubyのインストール

Rubyについては、最新版をサクッと入れたいのでapt-getでなくrbenvを用いてインストールする

$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv

rbenv用の初期化コマンドをbashrcに追加。これでrbenvディレクトリ経由でrubyを実行できるようにする。

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ exec $SHELL

rbenvのプラグインで、rubyをインストールするためのruby-buildをインストール

$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
$ exec $SHELL

rbenvを用いて、現在の最新の安定版であるRUby2.4.1をインストール

$ rbenv install 2.4.1

rbenvで利用するRubyのバージョンを、先程インストールした2.4.1にする

$ rbenv global 2.4.1

Rubyのパッケージ管理ツールであるgemをインストール

$ apt-get install gem

gemがドキュメントもインストールするのを抑止するため、.gemrcに以下を記述

install: --no-document
update: --no-document

gemをインストールする度に自動でrbenbをrehashしてくれるrbenv-rehashをインストール

$ gem i rbenv-rehash

gemの依存管理をしてくれるbundleをインストール

$ gem i bundle

Ruby on railsの導入

railsをインストール

$ gem install rails

5.1.0がインストールできたことを確認

$ rails -v
Rails 5.1.0

mySQLをインストール

$ apt install mysql-server mysql-client

なんか以下も必要らしいのでインストール

$ sudo apt-get install libmysqld-dev

mysqlserverを起動

$ /etc/init.d/mysql start

railsアプリケーションの雛形を作成

$ rails new myapp -d mysql

雛形がデキていることを確認

$ ls
Gemfile  Gemfile.lock  README.md  Rakefile  app  bin  config  config.ru  db  lib  log  package.json  public  test  tmp  vendor

rails用のDBを作成

$ rake:db

DBがデキていることを確認

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| myapp_development  |
| myapp_test         |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.01 sec)

railsアプリケーションを起動

rails s -b 0.0.0.0 -p 3000

が、何故かエラーが出る。gemライブラリが足りない的なエラーだがどうみても足りている。ググってもどうしても解決できなかったので、該当するコードをコメントアウト。調べてみるとタイムゾーン関係に必要になるそうなので、学習段階では大きな影響を受けないと判断。

myapp/vendor/bundle/ruby/2.4.0/gems/activesupport-5.1.0/lib/active_support/railtie.rb

 19       #begin
 20       #  TZInfo::DataSource.get
 21       #rescue TZInfo::DataSourceNotFound => e
 22       #  raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
 23       #end
 24       #require "active_support/core_ext/time/zones"
 25       #zone_default = Time.find_zone!(app.config.time_zone)
 26
 27       #unless zone_default
 28       #  raise "Value assigned to config.time_zone not recognized. " \
 29       #    'Run "rake time:zones:all" for a time zone names list.'
 30       #end
 31
 32       #Time.zone_default = zone_default

改めてrailsアプリケーションを起動。無事に起動。

=> Booting Puma
=> Rails 5.1.0 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.8.2 (ruby 2.4.1-p111), codename: Sassy Salamander
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000

Railsアプリケーションの起動をブラウザで確認する

  • rails用のWebサーバはコンテナ内の3000番ポートで起動している
  • コンテナ起動時に、Dockerホストの8081番ポートをコンテナの3000番ポートにポートフォワーディングするように指定している
  • Macの8081番ポートをDebian(Dockerホスト)の8081番ポートにポートフォワーディングするように設定している(Vagrantfileにて)
    以上より、Macのブラウザでlocalhost:8081にアクセスすることで、コンテナ内で起動しているWebサーバにリクエストを送ることができる。

実際にブラウザを用いてアクセスしてみると、以下のようにrailsのウェルカムページが表示され、Dockerコンテナ側でもアクセスログが表示されているので、環境構築が成功したことがわかる。

Started GET "/" for 10.0.2.2 at 2017-05-03 14:19:10 +0000
Cannot render console from 10.0.2.2! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by Rails::WelcomeController#index as HTML
  Rendering vendor/bundle/ruby/2.4.0/gems/railties-5.1.0/lib/rails/templates/rails/welcome/index.html.erb
  Rendered vendor/bundle/ruby/2.4.0/gems/railties-5.1.0/lib/rails/templates/rails/welcome/index.html.erb (2.7ms)
Completed 200 OK in 115ms (Views: 5.4ms)

Dockerイメージのコミット

※ 以降ではコンテナから切断し、Dockerホスト側で作業を行う

4の項で、rails用の環境が構築されたコンテナが出来上がったので、このコンテナを元に新たなイメージをコミットする。

DockerHubにpushするためには、イメージ名が”DockerHubのユーザ名/イメージ名”である必要があるので、ここではそれに従ってコミットする

$ docker commit my_ubuntu sa2knight/rails

イメージ一覧に新しいイメージが追加されていることを確認。元のUbuntuとくらべて、様々なツールをインストールしたので容量が増大していることがわかる

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sa2knight/rails     latest              519638e57a05        22 hours ago        1.55 GB
ubuntu              latest              f7b3f317ec73        8 days ago          117 MB

DockerHubへのpush

ここでは、DockerHubに作成したイメージをpushするが、既にDockerHubアカウント及びリポジトリは作成済みで、ログインも完了しているものとする。

DockerHubへのpushは以下のコマンドで行う

$ docker push sa2knight/rails
The push refers to a repository [docker.io/sa2knight/rails]
d675a105e8a6: Pushing [========================================>          ] 1.153 GB/1.431 GB
d675a105e8a6: Pushed
08f405d988e4: Pushed
511ddc11cf68: Pushed
a1a54d352248: Pushed
9d3227c1793b: Pushed

latest: digest: sha256:2c8b2bb969347c41be37d8bb788e9c5a531b6478c8f4089039692d28bd74ec5d size: 1570

1.5HBをアップロードするのでかなり時間がかかるが、気長に待ってたらいつのまにか終わった。

DockerHubにアクセスすると、イメージがアップロードされていることが確認できる。

参考

DebianにDockerをインストールして基本的なコマンドを使ってみる

前提

以下の環境にDockerを導入する

要素 バージョン
Debian 8.6
Docker 1.13.0

概要

Debian8.6にDocker1.13.0をインストールし、そこでCentOSのコンテナを作成する。コンテナで適当に作業を行い、コミットして再利用するところまでをチュートリアルする。Dockerそのものに関する説明はそんなに無い。Dockerfileによる構築も扱わない。Dockerの雰囲気が味わえれば良いかなぐらい。

Dockerとは

Dockerはサーバ仮想化ソフトウェアの一つ。ただし、VMWareなどの、ハイパーバイザ型における完全な仮想化を提供するのではなく、ホストOSのカーネルを共有し、その上に「コンテナ」と呼ばれるOSのシステムレベルで仮想化されたゲストOSを取り扱う。

つまり、VMWareなどの仮想化と比べると不完全な仮想化で、ゲストOSの独立レベルは低い。Dockerではそのような構成にすることで以下のメリットが得られる。

  • 個別にOSを立ち上げる必要がないので作成や起動、破棄が高速
  • 使用する資源(CPU/メモリ/ストレージ)が少ない
  • オーバーヘッドが少なく性能劣化が殆ど無い

よって、Dockerの使い方としては、永続的に稼働している環境というよりは、頻繁に作成、破棄が行われる使い捨ての環境に用いることが向いていると言える。

個人的には開発環境を手軽に構築、共有するのに使っていけたら良いなと思う

Dockerのインストール

DockerはホストOSのカーネルを共有するので、当然Linux上に構築するのが望ましい。一応WindowsやMacでもDockerを導入することができるが、本記事ではMac上に構築したDebianの上にDocker環境を構築する。

例によってapt-getでインストールしたいところだが、Debianに標準で含まれてるaptリポジトリにdockerが含まれていないので、手作業でリポジトリを追加する必要がある。

/etc/apt/sources.list

が、aptのリポジトリリストなので、これに以下を追記する。ドメイン的に日本のDebian公式リポジトリなんだと思う。

deb http://ftp.jp.debian.org/debian/ sid main
deb-src http://ftp.jp.debian.org/debian/ sid main

で、アップデート

$ sudo apt-get update

dockerをインストール

$ sudo apt-get install docker.io

インストールできたことを確認

docker -v
Docker version 1.13.0, build 49bf474

Dockerイメージのインストール

Dockerでコンテナを作成するためには、元となるイメージが必要になる。

Dockerには、DockerイメージのリポジトリであるDockerHubを通じて、Dockerイメージを共有する機能があるので、今回はそちらからCentOSのDockerイメージをインストールする。

権限周りがやかましいのでここからはsudo権限を持たせる

$ sudo -s
# whoami
root

DockerHubからDockerイメージをダウンロードする場合は、docker pullコマンドを使用する。今回はCentOSをダウンロードする。

# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
93857f76ae30: Already exists
Digest: sha256:4eda692c08e0a065ae91d74e82fff4af3da307b4341ad61fa61771cc4659af60
Status: Downloaded newer image for centos:latest

ダウンロード済みのDockerイメージの一覧の確認は、docker imagesコマンドで行う。centosのDockerイメージがダウンロードされていることが確認できる。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              a8493f5f50ff        3 weeks ago         192 MB

Dockerイメージが仮想マシンのイメージと同じようなものと考えると、192MBというのは実に小さい。仮想マシンイメージと異なり、カーネルが含まれていないからである。

DockerコンテナによるHello World

DockerコンテナはDockerイメージから生成される仮想環境の実体である。一つのイメージから複数のコンテナを生成できるので、オブジェクト指向におけるクラスとインスタンスの関係のようなものだ。

コンテナ起動は、docker run コマンドを用いる。といっても、コンテナはホストOSのカーネルを用いてプロセスを実行するものなので、どんなプロセスを実行するかを指定する必要がある。

ここでは、”Hello Docker World”という文字列をechoするプロセスを実行するだけのコンテナを立ち上げてみる。

# docker run centos echo "Hello Docker World!"
Hello Docker World!
#

“Hello Docker World!” の文字列が出力され、コマンドの実行は終了する。ではこの時コンテナはどのような状態なのか、docker psコマンドで確認する。psコマンドは基本的にプロセスが動いているコンテナの一覧を表示するが、-aオプションを付与することで終了しているコンテナも表示する。

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                          PORTS               NAMES
627496810cd6        centos              "echo 'Hello Docke..."   About a minute ago   Exited (0) About a minute ago                       angry_blackwell

627496810cd6がコンテナのID(ユニーク)で、angry_blackwellがコンテナの名称である。名称はユニークでない可能性もあるが、コンテナ生成時に任意の名称を付けることができる。

このコンテナはコマンド”echo ‘Hello Docker…”を実行完了し、Exited状態に移行している。

コンテナの削除

前項で作成したコンテナは、Hello Docker World!を出力してお役御免なので、docker rmコマンドを用いて削除する。削除の際はコンテナIDがコンテナ名を指定する。特に重複の可能性がないのであれば、可読性のあるコンテナ名を使ったほうが良さそう。

# docker rm angry_blackwell
angry_blackwell

削除されたことを確認

docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

コンテナを作成し、アクセスする

“アクセスする”という言い方には語弊がある気がするが、つまりSSHでアクセスしたときみたいにコンテナ内でシェルを使いたいということである。前項の用に、コンテナを起動する際にプロセスを指定することで、コンテナはプロセスを実行し、実行完了するまで稼働し続ける。

つまり、コンテナで実行するプロセスにシェルを指定してあげればよい。ここではbashを用いてシェルを利用することにする。また、-itオプションを付与することで、現在の標準入出力を引き継ぐことができるので、シェルを利用するためには必須となる。

# docker run -it centos /bin/bash
[root@a3936fcb8f31 /]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

コンテナ内でシェルを利用できるようになり、catコマンドでコンテナ内のOS情報ファイルを出力できていることがわかる。CentOSと書かれているが、実際にはホストOSであるDebianのカーネルを利用している。ややこしい。

コンテナ内でRubyをインストールする

コンテナ内に開発環境を作る、というほど大層なことは本記事では行わないが、その前進としてRubyをインストールして、適当なスクリプトを作成してみる。

カーネルはDebianのものを使ってるが、コンテナはCentOSなので、apt-getではなくyumを用いてRubyをインストールする。ここではRubyのバージョンとかは気にせず、簡単にインストールできる方法を用いる。

[root@a3936fcb8f31 /]# yum install ruby

インストールできたことを確認。どうやらこのコンテナ内のyumで標準でインストールできるRubyは2.0.0らしい。だいぶ古い。

[root@a3936fcb8f31 /]# ruby -v
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]

適当にスクリプトを作成する。と思ったらvimも入っていないので先にvimをインストールする

[root@a3936fcb8f31 /]# yum install vim

インストールしたvimで、/fizzbazz.rb を作成する。フィズバズについてはWikipediaを参照。ここでは、コマンドライン引数Nを取り、1〜Nに対してのフィズバズを行うプログラムを作成する。カッコいいアルゴリズムでも使おうと思ったが、コードの内容は本記事とは関係ないので普通に書く。

N = ARGV[0].to_i
N.times do |m|
  if m % 3 == 0 && m % 5 == 0
    puts "Fizz Buzz"
  elsif m % 3 == 0
    puts "Fizz"
  elsif m % 5 == 0
    puts "Buzz"
  else
    puts m
  end
end

実行してみるとこんな感じ

root@a3936fcb8f31 /]# ruby /fizzbazz.rb 10
Fizz Buzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz

フィズバズを持つDockerイメージを作成する

前項では、コンテナ内でRubyとvimのインストール及びフィズバズプログラムの作成を行った。しかし、これからはあくまでコンテナ内に存在するだけで、元となったDockerイメージに存在するものではない。したがって、本コンテナを削除してしまえば前項の作業は水の泡となってしまい、再利用することができない。

そこで、本コンテナを元にしたDockerイメージを新たに作成する。つまり、「CentOSのイメージ」を元に、「CentOSの中にRubyとVimとフィズパズスクリプトが入ったイメージ」を作成するということだ。

コンテナからイメージを作成するには、docker commitコマンドを用いる。以下では、”unruffled_blackwell”(本コンテナの名前)を元に、”fizzbazz”というイメージを作成する。

# docker commit unruffled_blackwell fizzbazz
sha256:7bf2cab2f57325c76c67affd54f7545ecc7ecde41925e7cd2404ba6c602e05a7

イメージが作成されたことを確認。RubyとVimを入れたせいで容量がかなり増えている。それでも348MBだが。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
fizzbazz            latest              7bf2cab2f573        26 seconds ago      348 MB
centos              latest              a8493f5f50ff        3 weeks ago         192 MB

作成したイメージから新たにコンテナを生成する

とりあえず先程Rubyやvimをインストールしたコンテナはもう不要なので削除する。以下は全てのコンテナを削除するおまじない的なコマンド。といっても、「全てのコンテナ一覧のコンテナIDのみ標準出力し、それらをdocker rmの引数にする」という一連の処理を行っているだけ。

# docker ps -aq | xargs docker rm
a9f5293d88a0
a3936fcb8f31
0357fffe82b2

これでRubyやVimがインストールされたコンテナが削除された。インストール作業は水の泡となってしまった。

# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

ということはもちろん無く、以下のように先程作成したコンテナを用いてフィズバズプログラムを実行できることが確認できる。

# docker run fizzbazz ruby /fizzbazz.rb 10
Fizz Buzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz

まとめ

以上より、Dockerを用いることで非常に手軽にCentOSの環境を導入し、そこでRubyの開発環境(の卵)を作成することができた。さらに、Ruby開発環境を持ったCentOSのイメージを作成し、手軽に再利用できるようになった。

また、本記事では割愛しているが、DockerHubを用いて、本記事で作成したイメージをpushすることで、他のユーザがそれを再利用することもできる。逆に他のユーザが作成したイメージからコンテナを作成することもでき、例えばRubyの開発環境に留まらず、Ruby on railsの開発環境一式が揃ったイメージなども数多く出回っている。

つまり、今後何らかの技術を使って開発を行いたくなったら、その開発環境に適合するイメージを探して、docker pullするだけでスグに環境構築を行えるということだ。
完全に適合したイメージが無ければ、近いものをpullし、自分でカスタマイズしてcommit,pushすればさらに特定の目的に特化したイメージを流通させることができる。

今回、本記事を書くために初めてDockerを利用したが、まだまだ使いみちは模索中で、基礎的なコマンドしか抑えられていないので、今後はさらに実用的な使い方ができるように勉強し、実務にも取り入れられたらなと画策している。