しおブロ!

ITの知見や備忘録、レビューなど。しおぽん(shiopon01)のブログ

Dockerfileの利用手順

目次

概要

VMを使ってチームメンバー全員が同じ開発環境を整えようとすると、とにかく手間がかかる。Vagrantで生成した400MB以上あるboxファイルを全員に配布しても良いが、利用していく中で好き勝手にカスタマイズされ、気付けば全く別の環境で開発していたという状態もあり得ない話ではない。

そこで、Dockerfileの出番がある。Dockerfileは、全ての環境で同じDockerのイメージを作成するための設定ファイルだ。実態は、ただのテキストファイルである。

このテキストファイル1つで、DockerHubから指定のイメージの取得とコンテナの作成、記載されたコマンドを実行、環境変数を変更し、全く同一の環境を整えてくれる。そこで整えたものを、新しい一つのイメージとして提供してくれるのがDockerfileの役割だ。

以下の例では、ruby:2.4.2のイメージを元に、nodejsの9系をインストールできる。
最後は環境変数ROOTに設定されたディレクトリに移動しているので、このDockerfileから生成されたイメージで作られたコンテナは、/var/wwwからスタートする。

FROM ruby:2.4.2

RUN curl -sL https://deb.nodesource.com/setup_9.x | bash
RUN apt install -y nodejs

ENV ROOT /var/www
WORKDIR $ROOT

大まかな使い方は公式リファレンスが丁寧に書いてくれているので割愛。
ここには、ややこしいCMDとENTRYPOINTADDとCOPYの違いを記載する。

Dockerfileリファレンス

起動時コマンド、CMDとENTRYPOINT

Dockerfileにこれを記述することで、そのイメージのコンテナを実行する際に実行するコマンドを設定できる。ここでbashを設定しておけば、docker runする時にわざわざ指定しなくても良いということになる。
例えば、こんな感じで設定する。

CMD ["ping","127.0.0.1","-c","100"]
ENTRYPOINT ["ping","127.0.0.1","-c","100"]

1つのDockerfile内では、CMDとENTRYPOINTはそれぞれ1回ずつしか使えない。併用は可能になっている。(複数記載されている場合、最後のコマンドが実行される)

CMDで指定したコマンドは、Docker run時に指定したコマンド指定で上書きされてしまう。

$ docker run --rm ubuntu cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"

ENTRYPOINTで指定したコマンドは、Docker run時に指定したコマンド指定で上書きされない、というのが大きな違いだ。 ただし、ENTRYPOINTでもdocker run --entrypoint=""を使用されると上書されてしまうので注意。

$ docker run --rm ubuntu cat /etc/debian_version
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.028 ms

["command"]とcommandの違い

起動時のコマンドでも2種類あったが、さらにそれぞれ2種類の書き方がある。 括弧で囲む書き方と、括弧で囲まない書き方だ。

括弧で囲んだコマンドは、シェルを介さずにコマンドが実行される。["command"]
一般的にはこちら使われる。

CMD ["ping","127.0.0.1","-c","100"]
ENTRYPOINT ["ping","127.0.0.1","-c","100"]

#=> ping 127.0.0.1 -c 100

括弧で囲まないコマンドは、シェルを介してコマンドが実行される。

CMD ping 127.0.0.1 -c 100
ENTRYPOINT ping 127.0.0.1 -c 100

#=> /bin/sh -c ping 127.0.0.1 -c 100

特徴を活かして併用する

CMDENTRYPOINTを両方書いた場合、連結されて1行のコマンドとして扱われる。
コマンドのみ固定にしておいて、引数を変更するなどの使い方ができる。

ENTRYPOINT ["ping"]
CMD ["127.0.0.1", "-c", "50"]

こう書くことで、dcoker runの際にコマンドは書き換え不可、引数を書き換え可能にできる。
引数が無い場合は127.0.0.1pingが送られ、引数がある場合はそのIPにpingを送るコマンドだ。

$ docker run ubuntu localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.027 ms

(DockerfileにENTRYPOINTを書かなかった場合、docker-compose.ymlに下記のように追記することで、サービスの全ての設定が終わった後に実行するコマンドを設定することが出来る。)

app-name:
  command: node app.js

ファイルの転送、ADDとCOPYの違い

ADD [ソース] [送信先]で、ホストに存在するファイルやディレクトリをコンテナにコピーできる。このソースファイルがtarアーカイブであった場合、自動的に解凍・展開される。

ADD default.conf /etc/apache2/sites-available/default.conf

COPY [ソース] [送信先]で、ホストに存在するファイルやディレクトリをコンテナにコピーできる。こちらはtarを展開しない。

ADD default.conf /etc/apache2/sites-available/default.conf

ほとんど同じなので、ADDCOPYを明確に使い分ける必要はない。(ADDだけでよさそう)

Dockerのインストールと利用手順

目次

概要

Dockerとは、仮想化技術「コンテナ」を利用したOS仮想化ツールだ。
VMWareなどのホスト型(OSに土台となるソフトウェアをインストールしてその上で仮想OSを立ち上げる)とは違い、OSの一部のみを仮想化して利用するため、非常に軽量に扱える。
さらに、各コンテナはアクセスできるリソースや権限を制限/分離したホストOSの「プロセス」として扱われるため、コンテナを管理するコストはプロセス管理とほとんど変わらない。
コンテナはホストOSのLinuxカーネルを共有するので、カーネルとコンテナの関係はJVMとJarに近い。(Docker for Windowsでは、LinuxカーネルHyper-Vで動かしているっぽく、少し手間。Linux系での利用を推奨)

Dockerのインストール方法

おおまかなインストール手順は以下の通り。ふつう、Docker Community Edition (CE)を利用する。

Install Docker | Docker Documentation

Windows

Docker for Windowsをインストールする。
基本的にはインストール手順に従っていけば良いが、WindowsではHyper-Vを有効にしなければならない。

Install Docker for Windows | Docker Documentation

Mac

Docker for Macをインストールする。
ほんとうにそれだけで動いたと思う。

Install Docker for Mac | Docker Documentation

Linux

これも公式のドキュメントにあるやつでだいたいOK。
しかし、そのままだとdockerコマンドの利用にsudoが必要になるので、ユーザーをdockerグループに入れてあげる。

Ubuntuだと、こんなかんじで。

sudo apt -y install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt -y install docker-ce
sudo groupadd docker
sudo usermod -aG docker $USER

Get Docker CE for Ubuntu | Docker Documentation

利用手順

とりあえず利用してみるのが一番早い。

Dockerでコンテナを作成するためには、まずコンテナを作成するための型であるイメージが必要だ。イメージがたい焼き器なら、コンテナがたい焼きという認識で問題ない。

イメージはDockerHubという公式のイメージ共有サービスからダウンロードすることができる。まず、目的のイメージを検索する。今回は練習で、ubuntuのイメージをダウンロードして使ってみる。検索する時はdocker searchが使える。

(イメージはブラウザのDockerHubで探したほうが楽)

https://hub.docker.com/

docker search ubuntu

今回はOFFICIALの、公式が出しているubuntuイメージを利用する。
DockerHubのイメージをローカルに落としてきたい場合はdocker pull [イメージ名]が使える。この時、ubuntu:17.04のようにタグを指定すれば、指定のタグのバージョンを手に入れる事ができる。何も付けなければ、latest (最新)のイメージが手に入る。

docker pull ubuntu

今までにダウンロードしたイメージはdocker imagesで確認できる。この時に表示されるREPOSITORYIMAGE IDを指定して、イメージの削除も可能。

docker images
docker rmi [指定イメージ]

コンテナの生成と起動はdocker run [イメージ名]で行う。しかし、役目を終えたdockerのコンテナすぐに消えてしまうので、このままでは何も起こらない。イメージ名の後に、実行したいコマンドが必要になる。例えば、さっきダウンロードしたubuntu:latestecho 1を実行する場合。

docker run ubuntu echo 1

コマンドを指定するとubuntu1を出力して、消えてしまう。消えると言っても実際は消滅しているわけではなく、コンテナのステータスがExitedになって寝ているだけだ。その様子は、docker ps -aで確認できる。この時に表示されるCONTAINER IDを指定して、コンテナの削除が可能。

Exitedのコンテナがたまっていくのは嫌なので、コンテナの終了時にコンテナは削除したい。その時は、runコマンドの--rmオプションが利用できる。

docker run --rm ubuntu echo 1

また、起動したコンテナの中に入って作業をしたいという場合もある。この場合、-itオプションが利用できる。

  • -i 対話モードでコンテナを起動
  • -t 疑似ターミナルでコンテナを起動
docker run -it --rm ubuntu echo 1

この時に表示される1は、dockerの疑似ターミナル内で表示される1になる。しかし、役目を終えたコンテナはすぐに消滅してしまう。ほんとうに中で作業をしたいなら、bashなどのshellを起動しよう。
exitなどでshellを抜けることで終了できる。

docker run -it --rm ubuntu bash

docker runのオプション

  • -d デタッチドモード(デーモン)でコンテナを起動
  • -i 対話モードでコンテナを起動
  • -t 疑似ターミナルでコンテナを起動
  • -v Data Volumeの指定(所謂、フォルダ共有)
  • -w 開始ディレクトリの指定(デフォルトはルート)
  • --name [名前] : コンテナに名前をつける:
  • --rm コンテナの終了時にコンテナをクリーンアップし、ファイルシステムを削除する
  • --reset [ポリシー] : 再起動ポリシーを設定(no, always, など)
  • -p ポートのバインド(例: 80:8080ならホスト80番でコンテナ8080番)
  • -e 環境変数設定(RAILS_ENV=development)

普通にdockerコマンドで利用するくらいなら、-it --rmくらいしか使わない(たぶん)。
その他はほとんど、docker-compose(後述)の設定ファイルで設定する。

よく使うコマンド

先述した、疑似ターミナルの対話モードでbashを起動など。
停止しない状態で元のターミナルに戻りたい(コンテナからデタッチ)なら Ctrl + P + Qを押せば良いらしい。

docker run -it --rm [image] bash

コンテナが増えた場合、このコマンドで全コンテナを削除できる。

docker rm $(docker ps -aq)

VMWareのUbuntuを入れ直したときのメモ

とりあえずUbuntuの情報を見たい

cat /etc/lsb-release # check Ubuntu version
df -h   # check Disk capacity
free -m # check Memory capacity

英字の設定

sudo dpkg-reconfigure keyboard-configuration

…を実行したのだが、そのターミナルを離れるとまた日本語入力に戻っている。。
結局、「システム設定」→「キーボードレイアウト」の入力ソースを「英語(US)」にするだけでよかったらしい。

フォルダ共有(VMWare

仮想マシン設定のオプションから「共有フォルダ」で、ホストマシンとの共有フォルダを設定。

インストール作業

VMWare Tools(VMWare

VMWare Workstation Playerの場合「Player>管理>VMWare Toolsのインストール」から

アップデート

sudo apt upgrade
sudo apt update

よく使うやつ

treeコマンドがコマンドで一番すきです。

sudo apt -y install tmux emacs24 vim htop tree

VSCode

vscode-doc-jp.github.io

SQLite3

sudo apt -y install libsqlite3-dev sqlite3

chrome

sudo apt install libappindicator1
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb

ruby

rubyのバージョン管理ではrbenvをずっと使っている。

sudo apt install -y rbenv libssl-dev libreadline-dev zlib1g-dev
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
rbenv install --list
rbenv install [version]
rbenv global [version]

gem install bundler railties rails && rbenv rehash

node

nodeのバージョン管理ではrbenvみたいなnodenvをずっと使っている。

git clone git://github.com/nodenv/nodenv.git ~/.nodenv
git clone git://github.com/nodenv/node-build.git ~/.nodenv/plugins/node-build
echo 'export PATH="$HOME/.nodenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(nodenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
nodenv install --list
nodenv install [version]
nodenv global [version]

docker

sudo apt -y install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt -y install docker-ce
sudo groupadd docker
sudo usermod -aG docker $USER

BIOSが起動しなくなった時にやったこと

先日、GTX670をGTX1070に換装した際にBIOSが起動しなくなった。
結局のところ原因はメモリにあったようで、メモリを外して解決したのだが、そこに至るまでの過程を記述しようと思う。
メモリが悪かったのか、ボードのソケットが悪かったのかはまだ確かめていない。新しいGPUでゲームをしたかった。

PC掃除から換装まで

GPUを換装する前に、PCの中があまりにも汚かったので、ファン、電源、ボード上のホコリの塊などを掃除した。この際、CPUファンを取り外してグリスを塗り直した。
今思えば、ここで起動確認をしておけばよかったのだと思う(おそらく、この時点でもうメモリか、ソケットは死んでいたのだろう)

そのままGPUを換装して電源を入れると、ファンが全力で回転して止まらなくなった。つまり、BIOSが起動しなくなっていた。

BIOSの死から原因特定まで

構成が変わったとかで起動しないのかと思い、とりあえずCMOSクリアしてみたが起動せず。

それならとグラボの不良を疑い、とりあえずGTX1070を外して電源を入れてみた。
起動しない。グラボの問題でないことが判明。この時にSOUND BLASTER Zも抜いた。

個人的にはCPUが怪しかった。CPUファンを設置する際、不手際(または静電気)で壊してしまったのではないかと心配だった。
確認のためにCPUを外して電源を入れた時、PCは3秒ごとに再起動を繰り返した。挙動が違うので、おそらくCPUは壊れていない。

ケーブルの接触不良も怪しかったので、刺し直してみる。起動しない。

とりあえず全部外そうと思い、SSD、HDDを外したがこれでもダメ。
ここで、4枚刺さっているメモリを1枚にしたところ、起動できた。

今までずっと挿しっぱなしで今まで動いており、今回の作業ではまったく触れていない場所だったので意外だった。
とりあえず、刺したら起動しなくなるメモリを見つけ、それを外すことで復活。(サクっと書いてあるが、ここに至るまでにけっこう時間がかかった)

やったことは大体こんなかんじで、よくあるやつ。取り出すのがめんどくさかったので、マザーボードはケースに入れたまま作業を行った。
どのパーツも5年は使っており、最悪、全部換装まであるなと考えていたので、出費がかさばらなくて嬉しい。。

構成

メーカーが分からないものがいくつかあるが、とりあえず構成も。

WindowsでJIS->USとCaps->Ctrl

備忘録

JISキーボード -> USキーボード

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters]

name value
LayerDriver kbd101.dll
OverrideKeyboardIdentifier PCAT_101KEY
OverrideKeyboardSubtype 0

Caps -> Ctrl

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]

name value
Scancode Map 00,00,00,00,00,00,00,00,02,00,00,00,1d,00,3a,00,00,00,00,00

参考

Windows/TIPS/レジストリを修正してCAPSLOCKの割り当て変更 - yanor.net/wiki

結局、はてなブログに帰る。

ブログサービスを転々としたが、なんだかんだ、はてなブログが無難な気がした。