はじめに
DockerをMacに入れた。Docker設定メモを書いて、Dockerに関しての知識が随分深まった。
はじめはdocker-compose
を使ってサイトを構築してみる記事を書こうと思ったのだが、あまりにも簡単にできてしまったのでdocker-compose
も含めた今まで得た知識をメモとして残しておきます。
この記事は僕のように全くDocker
を使ったことがない人向けの記事です。
これからDocker
で遊びたい方の役に立てればと思います。
前回の記事の書き直しになっている部分もあります。
Dockerとは?
Docker
の位置付けはVagrant
などと同じ仮想OSに近いポジションにいると思います。
しかし、大きく違う点としてDocker
はイメージベースで駆動するため構築や(DockerHubを使用した)コピーが簡単にできるところにあります。
Vagrant
とは違いプロセス内で実行されるため起動と終了があっという間に行えます。
(Vagrant
はプロセス単位で建てるので、複数起動するとメモリを大量に消費する。)
この利点を使うと、人が作ったイメージ(例えばRedmineなど)をもらってそのまま起動(コンテナ作成)すればあっという間にサイトなどの構築ができます。
僕もまだ使い始めなのでうまく活用できてませんが、この技術をうまく使うと自社内のツールなどを簡単に構築できるのではないでしょうか?
イメージの受け渡しについて
ただ、作成したイメージの受け渡しをするためにはDockerHub
を使用する必要があるため企業で使用するためにはプライベートリポジトリ(有料)を使う必要がありそうです。
→export/importを使えば可能でした。後述します。
金額は調べてませんが、十分使う価値があるのではないでしょうか?
僕は環境構築が苦手なので、誰かがイメージで環境を作ってくれるととても助かりますw
Dockerのインストール
Dockerを使うにあたって以下をはじめに入れておく必要がある。
- VirtualBox
- HomeBrew
Dockerを使うためには以下のコマンドを実行する。
$ brew install docker docker-machine
人が作ったイメージを使うのに便利なのでdocker-compose
も入れておく。
$ brew install docker-compose
インストールができたか確認する。
$ docker -v
Docker version 1.8.1, build d12ea79h
$ docker-machine -v
docker-machine version 0.4.1 (HEAD)
VMのインストールと削除
DockerはVM上で動くのでdocker-machine
を使ってVMをインストールします
$ docker-machine create --driver virtualbox dev
dev
の部分はVMの名前なので何でも良いです。
他のVMの名前と重ならないものを指定してください。
VM起動後にDocker
コマンドが操作するために、VMの設定をDocker
へ伝えます。
$ docker-machine env dev
このコマンドをみると、設定される項目が表示されます。
これをそのまま起動コマンドに組み込みます。
$ vi ~/.bash_profile
# 一番最後に設定
eval "$(docker-machine env dev)"
# 反映
$ source ~/.bash_profile
これでDocker
が使えるようになります。
また、VMを削除する場合は以下のコマンドで削除できます。
$ docker-machine rm dev
docker-machineで使うコマンド
docker-machine
はVMを立てた後に(僕は)使うことはほとんどありません。
一応記載してますが、まず覚えなくても良いでしょう。
IPアドレスの確認
VMのIPを確認できます。
$ docker-machine ip dev
192.168.99.100
SSHでイメージに入りたいときなどに使うので、あまり使いませんが覚えおておくといいと思います。
VMの確認
docker-machine
が管理しているVMを見れます。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
dev * virtualbox Running tcp://192.168.99.100:2376
VMへログイン
どうしてもVMの中に入りたくなったら使う・・・?
$ docker-machine ssh dev
VMの起動/終了コマンド
ローカルPCで動かしている場合はメモリの問題で、Docker
の状態をそのままにしながら落としたい時があると思います。
その場合は以下のように行います。
# 終了
$ docker-machine stop dev
# 起動
$ docker-machine start dev
# IPアドレスが変わる場合は必要に応じて起動後に一度実行する。
$ source ./bash_profile
Dockerで使うコマンド
主に使うのはDocker
コマンドになります。
僕が使っているコマンドを紹介します。
イメージ検索
何はともあれイメージを見つけなければDocker
を使えません。
$ docker search ubuntu
このコマンド以外にもDockerHub
の公式ページでも探せます。
検索したページの右側にDocker Pull Command
が書かれてますので、そのコマンドを叩けばイメージを取得できます。
イメージ取得
コンテナ起動するためのイメージを取得します。
$ docker pull ubuntu:latest
OFFICIAL REPOSITORYとしてこんなイメージも存在してますw
コンテナ作成(起動)
取得したイメージを起動するとコンテナ
と呼ばれる単位で起動します。
Docker
はコマンドベースで起動されるので、起動時にコマンドを渡す必要がある。
また、起動イメージをpull
してない場合は自動的に取得しに行ってくれる。
例えば以下のコマンドは取得したイメージを起動してecho "Hello World"
コマンドを実行させる場合は以下のコマンドを実行する。
$ docker run ubuntu:latest echo "Hello World"
Hello World
なお一度起動するとコンテナが残ってしまうので何度も上記のコマンドを叩かない方が良い。
(確認方法と削除方法は後述します。)
コンソールに入る場合は以下のコマンドを実行します。
$ docker run -it ubuntu:latest /bin/bash
この方法で起動すると、取得したイメージを起動するしてコンソールを出力することができる。
exit
を入力するとコンソールが終了してコンテナも終了します。
主なオプション
- -d:バックグラウンドで実行する(後述)。既定では、コンテナーをフォアグラウンドで実行するため、Webサーバーやアプリケーションサーバーなど常時実行するコンテナーで指定
- -i:コンテナーの標準入力を開く。/bin/bashなどでコンテナーを操作する際に指定
- -t:tty(端末デバイス)を確保する。/bin/bashなどでコンテナーを操作する際に指定
- -p {ホストのポート番号}:{コンテナーのポート番号}:Dockerサーバーのホストとポートマッピングを構成
ついに1.0がリリース! Dockerのインストールと主なコマンドの使い方 (2/3)より引用。
コンテナ?
僕がDocker
を学んでいて疑問だった点はイメージ
やコンテナ
の概念だった。
Docker
でいうイメージ
とはAWSのAMIs
とほとんど同じで、仮想OSのスナップショットとほとんど同じだ。
そのイメージ
を実体化(インスタンス化)したものがコンテナ
と呼ばれる。
コンテナ
は実施した命令が終わると終了してしまうが、コンテナ
自身は残るため再実行させたりすることができる。
コンテナ
はイメージ
の上で成り立っているため、イメージ
を削除するためにはコンテナ
を削除する必要がある。
この概念を抑えると同じイメージから幾つものコンテナを作成させれるのでDocker
の良さがわかってくる。(とにかく起動が早い!)
なお、コンテナ
という名前の通りで起動時に与えれるコマンドは一つだけです。
後述するsshd
でchef
を実行するような使い方は基本的に推奨されていないようです。
イメージ確認
現在保有しているイメージを確認するためには以下のコマンドで行える。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest 89d5d8e8bafb 13 hours ago 187.9 MB
コンテナ確認
イメージ同様でコンテナを確認する場合は以下のコマンドで行える。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9534b3aa773e ubuntu:latest "/bin/bash" 3 seconds ago Up 3 seconds ubuntu1
ここまでの記事を実施した人はまだコンテナが起動していないはずなので、上記のコマンドを実施しても何もでてこないはずだ。
すでに終了したコンテナも確認するためには-a
を付けて実施する。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9534b3aa773e ubuntu:latest "/bin/bash" About a minute ago Exited (0) 3 seconds ago ubuntu1
STATUS
がUp
になっているコンテナは起動中でExited
になっているコンテナは終了している。
NAMES
は指定しないと勝手につけられるので、実施する場合にname
を付けてあげると管理がしやすい。
ex)
以下のように--name
を付けて起動させるとNAMES
が指定される。
また、同じ名前をつけることはできないため誤って同じコンテナを増やしてしまうこともなくなるのでできるだけ名前を付けてあげよう。
$ docker run -itd --name ubuntu1 ubuntu:latest /bin/bash
この例ではコンテナをバックグランドで起動させているので、docker ps
で表示されるようになる。
以下の説明では注釈がない限りubuntu1
はコンテナ名
を指す。
コンテナに入る。
バックグランドで起動しているコンテナに入る場合は以下のコマンドで入れる。
$ docker attach ubuntu1
初めのコマンドは見えないので、その場合は以下のコマンドで入れば見れる。
(@hidekuroさんに教えてもらいました。)
$ docker logs CONTAINER_NAME && docker attach CONTAINER_NAME
一度入り込んで抜けるとコンテナは止まってる。
再度起動するためにはdocker start
を使用する。(後述)
コンテナの停止
起動しているコンテナを停止させる場合は以下のコマンドで行う。
$ docker stop ubuntu1
コンテナ起動
コンテナを再起動させる場合は以下のコマンドで行う。
$ docker start ubuntu1
このあとattach
する場合もあるが、コンテナの命令が常駐系の命令だった場合はこれだけでサービスが立ち上がる。
ex)
例えば以下のようなコマンドで立ち上げられたコンテナは、起動すればそのコンテナにSSHで接続することができる。
$ docker run -d -p 22 --name sshd test-sshd /usr/sbin/sshd -D
コンテナの削除
コンテナを削除するためにはコンテナを停止してから行う必要がある。
$ docker rm ubuntu1
ファイルの送受信
コンテナへファイルを送ったりもらう場合は以下のように行える。
$ docker cp test ubunt1:test/
$ docker cp ubunt1:test/test test
SCPとほとんど同じように使えます。
イメージの保存
作成したコンテナをイメージとして保存する場合は以下のように行う。
$ docker start ubuntu1
$ docker attach ubuntu1
root@93d9d73dff28:/# apt-get install -y nginx
root@93d9d73dff28:/# dpkg -l nginx
root@93d9d73dff28:/# exit
立ち上げたコンテナに対して変更を加える。(例ではnginxをインストールしている。)
変更内容をイメージに保存します。
$ docker commit ubuntu1 ubuntu/nginx
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu/nginx latest a3bbb2669586 7 seconds ago 206.1 MB
ubuntu latest e9ae3c220b23 3 weeks ago 187.9 MB
新しいイメージができてるので、今後はこのイメージからコンテナを作成することができる。
Nginxを起動する場合
おまけだが、上記のイメージを使ってnginxコンテナを80番ポートフォワードで起動する場合は以下のように行う。
$ docker run -d -p 80:80 --name nginx1 ubuntu/nginx /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
$ curl localhost:80
これでnginx
が実行できるが、、、Macでは実際は80番ポートは使えないのでこちらを参照して適当なポート番号を割り当てて実行するとnginxへアクセスできる。
イメージの削除
イメージの削除はそのイメージから作成されたコンテナを全て削除しないと実施できない。
$ docker rmi ubuntu
もしくは
$ docker rmi [IMAGE ID]
コンテナのexport
コンテナをファイルに保存する場合は以下のコマンドでできます。
イメージからではなくコンテナからコンテナ名
を指定してファイルに落とします。
$ docker export ubuntu > backupfile
ファイルからイメージへimport
export
したファイルからイメージにする場合は以下のコマンドでできます。
$ cat backupfile | docker import - backup/ubuntu:1
イメージのsave
イメージをファイルに落とす場合はsave
コマンドを使います。
$ docker save ubuntu/nginx > backupfile
or
$ docker save ubuntu/nginx | gzip > backupfile
ファイルサイズが大きいのでgzip
をする事をお勧めします。
イメージのload
ファイルイメージからイメージを取得する場合はload
コマンドを使います。
イメージ名やタグなどは保存したときと同じなので、自分でテストをしたい場合はイメージを削除してから行ってください。
$ docker load < backupfile
ですが、これを使えばファイルベースでイメージのやり取りができます。
Dockerfile
イメージを作成する際にpull
で取得しても良いのだが、Dockerfile
に命令を記載してpull
+レシピ
を入れてイメージを作成することができる。
これを使うとchef
のようにある程度準備が整った環境を用意することができる。
先ほどのnginx
を例にすると以下のようになる。
$ mkdir nginx
$ cd nginx
$ vi Dokerfile
Dockerfileの中身は以下のようになる。
FROM ubuntu
RUN apt-get install -y nginx
ADD index.html /usr/share/nginx/html/
この例ではindex.html
を配置しているので、同ディレクトリにindex.html
を用意する。
$ vi index.html
<h1>test</h1>
出来上がったDockerfileを使ってイメージを作る場合は以下のコマンドで行える。
$ docker build -t ubuntu/nginx:10 .
ubuntu/nginx
という名前でTAGを10
で作成する。
最後の.は現在のディレクトリを指している。
あとは以下のように起動すればnginxが起動する。
$ docker run -d -p 80:80 --name nginx1 ubuntu/nginx:10 /usr/sbin/nginx -g
VM上で他のポート番号と重なる場合は以下のようにポート番号を変えて実行すると良い。
$ docker run -d -p 18888:80 --name nginx1 ubuntu/nginx:10 /usr/sbin/nginx -g
ENTRYPOINTを使用する。
Dokerfile
を以下のように記載すると起動コマンドを省略することができる。
FROM ubuntu
RUN apt-get install -y nginx
ADD index.html /usr/share/nginx/html/
ENTRYPOINT /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
コンテナ起動まで行う。
$ docker build -t ubuntu/nginx:1.1 .
$ docker run -d --name nginx2 -p 62733:80 ubuntu/nginx:1.1
docker-compose
Dockerで即実行できる、社内・自宅向けオープンソースWebアプリなどのようなレシピを実行するためにはdocker-compose
を使用する。
冒頭でインストールは終わっていると思うので、実際に使って見る。
Dockerで即実行できる、社内・自宅向けオープンソースWebアプリに記載されているRedmineを入れてみる。
$ mkdir redmine
$ cd redmine/
$ vi docker-compose.yml
docker-compose.yml
に上記サイトに記載されている内容を記載する。
data00mysql:
image: busybox:buildroot-2014.02
volumes:
- /data/mysql:/var/lib/mysql
data00redmine:
image: busybox:buildroot-2014.02
volumes:
# 添付ファイル保存先
- /data/redmine/files:/home/redmine/data/files
# プラグイン
- /data/redmine/plugins:/home/redmine/data/plugins
# テーマ
- /data/redmine/themes:/home/redmine/data/themes
mysql:
image: mysql:5.6.24
environment:
MYSQL_ROOT_PASSWORD: password
volumes_from:
- data00mysql
ports:
- "3306:3306"
redmine:
image: sameersbn/redmine:2.6.3
volumes_from:
- data00redmine
# - data00gitbucket
links:
- mysql:mysql
ports:
- "80:80"
environment:
# REDMINE_HTTPS: true
# REDMINE_RELATIVE_URL_ROOT: /redmine
DB_USER: root
DB_NAME: redmine
DB_PASS: password
# SMTP_USER: google@gmail.com
# SMTP_PASS: password
イメージを作成する。
$ docker-compose up -d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c0f9bff7513b sameersbn/redmine:2.6.3 "/app/init app:start" 8 minutes ago Up 8 minutes 0.0.0.0:80->80/tcp, 443/tcp redmine_redmine_1
時間がかかるが上記のようになったと思う。
VMのポートフォワーディングを設定(僕は18888で登録した)してhttp://localhost:18888/
へアクセスするとRedmineが立ち上がっている事が確認できる。
Githubを見るとadmin/admin
で入れるようなので、実際に入ってみるとmysql
などとも連携されている事がわかる。
すごい・・・・
おまけ
ここから先はおまけです。
Chef
を使ってDocker
の環境を作れるのかの実験をしてみます。
Docker
にChef
を流し込むメリットがあるかどうかは置いておいて、、、やってみます。
こちらのサイトの通りにSSH接続できる状態のDockerイメージを作成します。
Chef
を流し込むまでは、上記のサイトの通りです。
Dockerfileの作成
サイトの通りのDocker
ファイルを作成します。
FROM centos
# Install
RUN yum update -y
RUN yum install -y sudo
RUN yum install -y passwd
RUN yum install -y openssh-server
RUN yum install -y openssh-clients
RUN /usr/bin/ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -C '' -N ''
RUN /usr/bin/ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -C '' -N ''
RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config
RUN sed -ri 's/#UsePAM no/UsePAM no/g' /etc/ssh/sshd_config
RUN echo 'root:root' |chpasswd
RUN sed -ri 's/#PermitRootLogin yes/PermitRootLogin yes/g' /etc/ssh/sshd_config
EXPOSE 22
イメージの作成
イメージを作成して起動します。
コンテナの名前は付けておいたほうが便利なので、sshd
という名前を付けておきます。
$ docker build -t test-sshd .
$ docker run -d -p 22 --name sshd test-sshd /usr/sbin/sshd -D
起動したコンテナを確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d77c46ce2216 test-sshd "/usr/sbin/sshd -D" 5 seconds ago Up 5 seconds 0.0.0.0:32768->22/tcp sshd
PORTS
の部分である0.0.0.0:32768->22/tcp
が重要です。
必要に応じてこちらを変更してください。
SSH接続を行う。
Docker
が動いているVMのIPアドレスをチェックします。
$ docker-machine ip dev
192.168.99.100
この二つの情報を使ってSSH接続を行います。
$ ssh root@192.168.99.100 -p 32768
パスワードはroot
です。
入れたことを確認できたので、ここからchef
を流し込みます。
Chefの準備
SSH接続の情報を記載します。
Host test-sshd
HostName 192.168.99.100
Port 32768
User root
念のため以下のコマンドで入れることを試します。
$ ssh test-sshd
ここで作成したchef
を使用します。
{
"run_list": [
"ruby"
]
}
と定義します。
(僕の作ったレシピはcentos
へnginx
をインストールする時に失敗するので、ruby
のインストールのみを行います。)
Chefの実施
それではchef
を流し込んでみましょう!
$ bundle exec knife solo prepare test-sshd
何度かパスワードを聞かれますので、上記の通りroot
を入力してください。
$ bundle exec knife solo cook test-sshd
を実施するとchef
で作成したレシピが流し込まれます。
$ ssh test-sshd
[root@d77c46ce2216 ~]# ruby -v
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
うまく入りましたね!
SSH接続に関して
このようにDocker
をsshd
で起動することによってVagrant
のように使えるようになります。
しかし、このように使うならVagrant
の方が煩わしさがないので利点があるかどうかは微妙なところです。
結局イメージをコピーすれば複数台のサーバーを建てれるので、あえてDocker
にChef
を流し込む必要はないかもしれません。
とはいえ、Vagrant
と同じことができるということは仮想OSとして使えるということになりますので覚えておく価値はありそうです。
(本番環境と同じイメージを作りたいときなどは便利だと思います。)
あとは・・・
イメージの共有をするためにはDockerHub
を使う必要があるが、今回は長くなったのでまたの機会にやってみようと思う。
また、ローカルPCのディレクトリをマウントさせてコンテナを起動する事もできるみたいだけど、これも今度やってみようと思う。
$ mkdir /host_data
$ echo "test123" > /host_data/file
$ docker run -v /host_data:/container_data centos /bin/bash -c "cat /container_data/file"
test123
[Docker] ホストのディレクトリをコンテナにマウントするより抜粋。
最後に
いろいろ記事を書いたおかげでDockerに関してある程度理解が出来てきた。
ただ、残念ながら今の状況ではDockerを使う機会がないのでこのメモでしばらくDockerとは離れてしまう。
せっかく覚えたので、機会があればローカルに便利機能をいろいろ入れたいところだが・・・
これも覚えておいた方が良いなどの情報があったら是非教えていただけると嬉しいです!
なお、このページが参考になったので載せておきます。
筆者について
筆者はTownSoftの屋号を掲げているフリーランスです。
お仕事お受けいたしますので、お気軽にご連絡ください。