とあるお兄さんの雑記

基本的に技術系の内容を書きますが、何を書くかは私の気分です。

Dockerを学ぶ第3回~コンテナ操作~

HTC Advent Calendar 2020の15日目を担当します、kurasherです。

第3回は起動したコンテナを操作する方法を学んでいきます。

コンテナを操作する

「コンテナの中に入って操作する」と言われると何を想像するでしょうか?私がDockerを学びたての頃にこんなことを言われたときは、いまいち理解出来ませんでした。
Dockerを学んでいる中、ずっと、

( ゚Д゚)ハァ?

という状態でした。

コンテナを操作するとは?

実際に試してみましょう。今回引っ張ってくるイメージはalpineという非常に軽量なLinuxです。ひとまず、Linuxに入るってことを理解してればいいかと思います。

一旦、イメージを探してみましょう。

$ docker search alpine
NAME                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
alpine                                 A minimal Docker image based on Alpine Linux…   6935                [OK]
mhart/alpine-node                      Minimal Node.js built on Alpine Linux           476
anapsix/alpine-java                    Oracle Java 8 (and 7) with GLIBC 2.28 over A…   460                                     [OK]
frolvlad/alpine-glibc                  Alpine Docker image with glibc (~12MB)          249                                     [OK]
gliderlabs/alpine                      Image based on Alpine Linux will help you wi…   183
alpine/git                             A  simple git container running in alpine li…   156                                     [OK]

いろんなものがありますね。このように必要に応じて自分が欲しいイメージを探すようにしましょう。

今回は一番上のOFFICIAL[OK]とあるalpineをpullしてきましょう。

$ docker pull alpine

これでalpineイメージを取得できました。この後、alpineのコンテナを起動して、alpineコンテナの操作をするには以下のようにコマンドを打ちます。

$ docker run -it --name alpine_con alpine /bin/sh
/ #


これでコンテナ内部に入れました。lsとか打つと

/ # ls
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var

と出力されます。めっちゃ遊べますよ。終わる場合はexitと打つか、Ctrl + Cでコンテナから抜け出せます。

/ # exit
$

Dockerコマンド解説

先ほど打ったコマンドは以下でした。

$ docker run -it --name alpine_con alpine /bin/sh
  1. docker runでコンテナの起動
  2. -itでコンテナ内部に入るように設定
  3. --name コンテナ名で起動するコンテナ名を指定。起動する際に毎回つける必要はありません。無くても大丈夫です。
  4. --name alpine_conの後ろは起動するコンテナのもとになるイメージを指定。今回はalpineイメージです。
  5. /bin/shalpineコンテナのシェルを起動

ちなみに、最後のシェルの起動の部分ですが、大抵のコンテナは/bin/bashを指定しますが、alpineだけは/bin/shを指定します。
理由は↓の記事を参考にしてください。
dockerでalpine linux ベースのcontainerに入って、shellを使いたいとき。

コンテナでWebサーバを動かす:ポートフォワーディング

コンテナでWebサーバを動かすための、ポートフォワーディングという技術について学びましょう。内容としては、外部からコンテナ内のサーバにアクセスするためのポートを指定するというだけの話です。

今回使用するイメージはNginx(エンジンエックス)と呼ばれるWebサーバーです。以下のようにして取得できます。

$ docker pull nginx

せっかくなので、適当な名前を付けてコンテナを起動します。

$ docker run --name nginx_con -p 8000:80 nginx

これでDocker Desktopならlocalhost:8000でコンテナ内部のnginxにアクセスすることが出来ます。

一方、Docker Toolboxlocalhost:8000としてもつながりません。
以下のコマンド打って、ipアドレスを取得します。

$ docker-machine ip default
192.168.99.100

私の場合は、192.168.99.100なので、これに先ほど指定したポート番号(8000)を指定することでアクセスすることが出来ます。
Docker Toolboxの場合:192.168.99.100:8000

Dockerコマンド解説

先ほど打ったコマンドは以下の通りです。

$ docker run --name nginx_con -p 8000:80 nginx

-pというオプションがポートフォワーディングにあたります。指定方法は簡単で、

-p ローカルPC(ホスト)側のポート番号:コンテナ(ゲスト)側のポート番号

となります。

コンテナ内部でもアクセスしてみる

せっかくなのでコンテナ内部からもアクセスできるか見てみましょう。
別ターミナルを起動し、まずは以下のコマンドでnginxコンテナ内部に入ります。

$ docker exec -it nginx_con /bin/bash
root@6cb84a6dac9a:/#


後はcurl localhost:80と打ちます。コンテナ内部からのアクセスのため、ポート番号は80を指定します。
下記の出力となればOKです。

root@6cb84a6dac9a:/# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

無事コンテナ内部からアクセスできました。

コラム:docker run -it とdocker exec -itの違い

そういえば、コンテナ内部に入る際にコマンドが若干違いましたね。
これの違いはコンテナが起動しているかいないかになります。

コンテナが起動していない場合、docker run -itを、
コンテナが起動している場合、docker exec -it
することで、コンテナ内部でいろいろ操作することが出来るようになります。

ちょっと試してみましょう。適当にnginxのコンテナを起動します。

$ docker run --name nginx_con --rm -d nginx #コンテナ起動 --rm:コンテナ停止後コンテナの自動削除 -d:バックグラウンドで起動
624a440e75a5e525dda9ef8430ab80cb85bfe586d40392d1584f0c02c2e8b905
$
$ docker ps # コンテナが動作しているかを確認
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
624a440e75a5        nginx               "/docker-entrypoint.…"   11 seconds ago      Up 9 seconds        80/tcp              nginx_con
$
$ docker run -it nginx_con /bin/bash # nginx_conに入れるか確認
Unable to find image 'nginx_con:latest' locally
C:\workspace\Docker Toolbox\docker.exe: Error response from daemon: pull access denied for nginx_con, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'C:\workspace\Docker Toolbox\docker.exe run --help'.
$
$ docker exec -it nginx_con /bin/bash # nginx_conに入れるか確認
root@624a440e75a5:/#

上記はnginxのコンテナを起動し、コンテナ内部に入るまでの一連の流れを示したものです。
docker run -it nginx_con /bin/bash # nginx_conに入れるか確認で、起動したnginx_conrunで入ろうとしていますが、nginx_conというイメージ名が無いよ、というエラーが出ています。

また、起動していないコンテナにexecしてもエラーが出ます。

$ docker ps # 起動しているコンテナの確認
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
624a440e75a5        nginx               "/docker-entrypoint.…"   8 minutes ago       Up 8 minutes        80/tcp              nginx_con
$ docker stop 6 # コンテナの停止 先ほど-dを指定してrunしたため、stopすれば自動削除される
6
$ docker ps -a # コンテナが立ち上がっていないかを確認
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$ docker exec -it nginx /bin/bash # コンテナが無い状態でexecを実行
Error: No such container: nginx


docker run -itdocker exec -itの違いを覚えておきましょう。

まとめ

今回の記事で取り上げたDocker コマンド一覧です。-d--rmの他にもオプションはたくさんありますが、ハンズオンで少しずつ試すのがいいかと思います。
次回からDockerfileなるものを使ってみます。

やること Dockerコマンド
イメージを探す docker search イメージ名
イメージの一覧表示 docker images
起動していないコンテナのコンテナ操作 docker run -it コンテナ名 イメージ名 コンテナ内で実行するコマンド
起動中のコンテナのコンテナ操作 docker exec -it コンテナ名 イメージ名 コンテナ内で実行するコマンド
コンテナをバックグラウンドで起動 docker run -d イメージ名
コンテナを停止後自動的にコンテナを削除するオプション docker run --rm イメージ名
起動中コンテナの停止 docker stop コンテナ名

参考

dockerでalpine linux ベースのcontainerに入って、shellを使いたいとき。

docker runとdocker execの違いの解説