Macで初めてDockerを使う際に覚えておくと良いこと

  • 53
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

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)"
# 反映
$ soruce ~/.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が書かれてますので、そのコマンドを叩けばイメージを取得できます。

DockerHub

イメージ取得

コンテナ起動するためのイメージを取得します。

$ 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の良さがわかってくる。(とにかく起動が早い!)

なお、コンテナという名前の通りで起動時に与えれるコマンドは一つだけです。
後述するsshdchefを実行するような使い方は基本的に推奨されていないようです。

イメージ確認

現在保有しているイメージを確認するためには以下のコマンドで行える。

$ 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

STATUSUpになっているコンテナは起動中で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の環境を作れるのかの実験をしてみます。
DockerChefを流し込むメリットがあるかどうかは置いておいて、、、やってみます。

EC2にDockerを入れてSSH接続する方法

こちらのサイトの通りに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接続の情報を記載します。

~/.ssh/config
Host test-sshd
  HostName 192.168.99.100
  Port 32768
  User root

念のため以下のコマンドで入れることを試します。

$ ssh test-sshd

ここで作成したchefを使用します。

nodes/test-sshd.json
{
  "run_list": [
    "ruby"
  ]
}

と定義します。
(僕の作ったレシピはcentosnginxをインストールする時に失敗するので、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接続に関して

このようにDockersshdで起動することによってVagrantのように使えるようになります。
しかし、このように使うならVagrantの方が煩わしさがないので利点があるかどうかは微妙なところです。

結局イメージをコピーすれば複数台のサーバーを建てれるので、あえてDockerChefを流し込む必要はないかもしれません。

とはいえ、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とは離れてしまう。

せっかく覚えたので、機会があればローカルに便利機能をいろいろ入れたいところだが・・・

これも覚えておいた方が良いなどの情報があったら是非教えていただけると嬉しいです!

なお、このページが参考になったので載せておきます。

Docker チートシート

筆者について

筆者はTownSoftの屋号を掲げているフリーランスです。
お仕事お受けいたしますので、お気軽にご連絡ください。