👻

dockerfileの設定コマンド①

2021/02/05に公開

はじめに

くーばねてすをやっつけるためにこれまでにLinuxさんとAWSさんと仲良くさせていただいたが、新たなステージに上がるためについにdockerさんに会いに行くことにした。dockerさんと仲良くなることでコンテナシステムの仕組みの理解とくーばねてすを倒すための調査をする。
今回はdockerさんでコンテナを開発して、くーばねてすでの構築の基礎的な部分を理解する。

概要

■dockerfileのコマンド
■FROM
■RUN
■ADD

をまとめた!(^_-)-☆

■dockerfileのコマンド

前回適当に作成したがコンテナを設定するコマンドがたくさんあったので設定コマンドについて勉強する。
dockerfile命令(コマンド)、意味ざっくり
|コマンド|意味|
| --- | --- | --- |
|FROM イメージ:タグ|コンテナのベースイメージ|
|RUN コマンド|FROMのベースイメージで実行するコマンド|
|ADD ソース コンテナ内宛先|ソースをコンテナ内宛先へコピーする|
|ENTRYPOINT |コンテナが実行するファイルを指定する|
|CMD|コンテナの実行時に実行されるコマンドを指定する|
|ENV <key>=<Value>|環境変数をセットする|
|EXPOSE <port>|公開ポートを設定する|
|USER <ユーザ名>|RUN,CMD,ENTRYPOINTの実行ユーザを指定する|
|VOLUME["/path"]|共有可能なボリュームをマウントする|
|WORKDIR /path|RUN,CMD,ENTRYPOINT,COPY,ADDの作業ディレクトリを指定する|
|ARG <名前>[=<デフォルト値>]|ビルド時の引数を定義する--bild-arg<引数>=<値>|
|LABEL <key>=<value> <key>=<value>|イメージのメタデータにラベルを追加する|
|MAINTAINER<名前>|イメージのメタデータに製作者を追加する|
ルールがたくさんある!('_')

dockerfileはGO言語で記述する。

■FROMコマンド

コンテナのベースイメージを指定する。

コンテナベースイメージの記述
FROM ベースイメージ:タグ

dockerのベースイメージ一覧
|種類|Docker Hubのイメージ名|
| --- | --- | --- |
|Linux|alpine,busybox,ubuntu,centos,debian,fedora,amazonlinux,opensuse,oraclelinux|
|プログラミング言語|node,golang,php,python,openjdk,ruby,jaba,jruby,perl,erlang,pypy,mono,gcc,rails,ibmjava,rust,swift|
|NoSQLデータベース|redis,mongo,memcached,cassandra,couchbase|
|SQLデータベース|postgres,mysql,mariadb,percona|
|WEBサーバー|nginx,httpd|
|Servlet/JSPサーバー|tomcat,jetty,websphere-liberty|
|コンテンツ管理|wordpress,ghost,drupal|
|コンテナ|registry,docker,swarm,hello-world|
|ログ分析|ElasticSearch,lnfluxDB,logstash,telegraf,kibana|
|CI/CD|maven,jenkins,sonarqube|
|スクラッチ|scratch|
ベースイメージやタグを詳しく検索したい時はdocke hubで検索する。
https://hub.docker.com/search?type=image
左上の検索窓からイメージを検索できる。↓

イメージを開くとタグ一覧もでてくる。↓

ターミナルからdocker hub のイメージ一覧を調べることもできる。

docker ターミナルから
$ docker search イメージ

docker hub の人気イメージだけを検索

docker ターミナルから
$ docker search --filter "stars=3" --filter "is-official=true" イメージ

1 つの Dockerfile 内に FROM を複数記述することが可能だが、複数のベースイメージがある時はマルチステージビルドで記述するとわかりやすくなる。
https://qiita.com/carimatics/items/01663d32bf9983cfbcfe

■RUN コマンド

RUNではFROMのベースイメージから作られたコンテナの中で実行するコマンドを指定する。
コマンドの記述形式にはshell形式exec形式がある。
https://docker.open-code.club/shell形式とexec形式の違い.html

shell形式はコマンド 引数で記述する。
/bin/shが実行ファイルでターミナルで入力するように、RUNの指令の後ろに普通にコマンドを続ける。ベースイメージにあったコマンドで記述する。

shell形式で記述
RUN コマンド 引数1 引数2
RUN記述例
RUN cat /etc/resolv.conf | grep 'nameserver'

RUNコマンド例
1コマンドにつき1行でしか設定できないので複数のパッケージをインストールをしたい時などは、わかりやすくなるように改行するなどしてパッケージが重複しないようにしたり、リストの更新が簡単にできるようにする。また、これによりプルリクエストの読み込みとレビューをわかりやすく表示することができる。。

RUN例
RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion

exec形式はシェルを通さずコマンドで直接実行するのが基本。コマンドや引数を囲むときシングルクォート'は使えないので注意する。シェルで実行したいなら、["/bin/bash", "-c", "コマンド 引数1 引数2"]のようにする。

exec形式で記述
# 直接実行(パイプなどは使えない)
RUN ["grep", "nameserver", "/etc/resolv.conf"]
# シェルで実行ならパイプとか使える
RUN ["/bin/bash", "-c", "cat /etc/resolv.conf | grep 'nameserver'"]

他にもexec形式でもシェルを通せば通常の環境変数を使えるなどルールがある。

# これはechoが直接実行でありそのまま$HOMEの5文字が出力されてしまう
RUN ["echo", "$HOME"]

# だからシェルで実行する
RUN ["/bin/bash", "-c", "echo $HOME"]

■ADD

ADDコマンドはソース(ファイル、ディレクトリ、tarファイル、URL)をコンテナ内にコピーする

ADDコマンド記述形式
ADD ソース コンテナ内宛先
記述例
ADD  ./message /message

ソースの部分にはワイルドカードを含めることができる。 その場合、Go 言語の filepath.Match ルールに従って処理が行われる。

記述例
ADD hom* /mydir/        # "hom" で始まる全てのファイルを追加
ADD hom?.txt /mydir/    # ? は1文字だけ一致します。例: "home.txt"

コピー先のソースのパーミッションは 600 となる。
https://docs.docker.jp/engine/reference/builder.html#add

ソースのパス指定は、ビルド コンテキスト(dockerfileがあるディレクトリ) 内でなければならないため、たとえば ADD ../something /something といった指定はできない。
docker build の処理では、コンテキスト・ディレクトリ(およびそのサブディレクトリ)を Docker デーモンに送信するところから始まるためだからだ。

ソース が URL 指定であって コンテナ内宛先 の最後にスラッシュが指定されていない場合、そのファイルを URL よりダウンロードして コンテナ内宛先 にコピーされる。

ソース が URL 指定であって コンテナ内宛先/(スラッシュ)だった場合、ファイルが指定されたものとして扱われ、URL からダウンロードして コンテナ内宛先/ファイル にコピーされる。 また ADD http://example.com/foobar / という記述は /foobar というファイルを作ることになる。 URL には正確なパス指定が必要になる。 以上の記述であれば、適切にファイルが追加される。 ( http://example.com では正しく動作しない。)

ソースがディレクトリである場合、そのディレクトリ内の内容がすべてコピーされる。 ファイルシステムのメタデータも含まれる。なのでコンテナ内宛先もディレクトリ指定をする。(末尾に/をつけない)
※ディレクトリそのものはコピーされない。 コピーされるのは中身だけになる。

ソースが ローカル にある tar アーカイブであって、認識できるフォーマット(gzip、bzip2、xz)である場合、1 つのディレクトリ配下に展開される。 ディレクトリのコピーあるいは展開の仕方は tar -x (アーカイブの展開)と同等になる。

複数のソースが直接指定された場合、あるいはワイルドカードを用いて指定された場合、コンテナ内宛先 はディレクトリとする必要があり、末尾には / をつけなければならない。
コンテナ内宛先の末尾にスラッシュがなかった場合、通常のファイルとみなされるため、複数のソース の内容は 一つのファイル に書き込まれることになる。

まとめ

(ノД`)・゜・。

Discussion