LoginSignup
0
1

More than 3 years have passed since last update.

Dockerfileのスニペットのレビュー&Dockerfileベストプラクティスのまとめ

Posted at

このチュートリアルでは、Alibaba Cloud上でのDockerfileの使用方法について実践的な経験を積むことに焦点を当てています。

本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。

Alwyn Botha, Alibaba Cloud Tech Share Author. Tech Shareは、技術的な知識やベストプラクティスをクラウドコミュニティ内で共有することを奨励するAlibaba Cloudのインセンティブプログラムです。

このチュートリアルは、コピー&ペースト、シェル、実行するコマンドがないため、最初の3つのチュートリアルとは異なります。

このチュートリアルの手順に従うには、最新バージョンのDockerがインストールされているAlibaba Cloud Elastic Compute Serviceインスタンスにアクセスできることを確認してください。LinuxサーバにDockerをインストールする方法については、このチュートリアルを参照してください。

このチュートリアルは以下の部分で構成されています。

1、Dockerfilesのいくつかのスニペットのレビューは https://hub.docker.com にあります。
2、これらのスニペットからの洞察をまとめたデモDockerfileを構築します。
3、Dockerfileの用語集まとめテキスト
4、Dockerfileの成功事例まとめ
Dockerfilesのスニペットのレビューは順不同です。

スニペットのいくつかは非常に基本的な見識しかないことに注意してください - 心配する必要はありません。それらの基本的な概念の多くを組み合わせると、質の高いDockerfileを作成することができます。

Dockerfilesのスニペット - EXPOSEのレビュー

https://github.com/docker-library/cassandra/blob/0e270a93b53119818f9c71fa273cda3a07d0bf5c/2.1/Dockerfile

# 7000: intra-node communication
# 7001: TLS intra-node communication
# 7199: JMX
# 9042: CQL
# 9160: thrift service
EXPOSE 7000 7001 7199 9042 9160
CMD ["cassandra", "-f"]

このスニペットはDockerfileの右下にあるものです。

他の人がやっているように、ランダムに散らばっているEXPOSE命令を見つけるためだけにDockerfile全体を読みに行く必要はありません。

ポート番号がきちんと番号順に並んでいます。ポート番号はすべて簡潔に書かれている。簡潔で完璧 - どのポートが何をするのかを一言で覚えておくだけでいい。

正確で完全 - #doclineのポート番号とEXPOSEの行のポート番号が一致しています。矛盾はありません。

あなたのEXPOSEはプロフェッショナルで初心者にも優しく見えなければなりません。

Cassandraとは何か?

https://en.wikipedia.org/wiki/Apache_Cassandra から参照

Apache Cassandraは、フリーでオープンソースの分散型ワイドカラムストア、NoSQLデータベース管理システムで、多くのコモディティサーバにまたがる大量のデータを処理するように設計されており、単一障害点のない高可用性を提供します。

Cassandraは、複数のデータセンターにまたがるクラスタに対して堅牢なサポートを提供し、非同期マスターレスレプリケーションにより、すべてのクライアントに対して低レイテンシの操作を可能にします。

Dockerfilesのスニペット - ユーザーIDのレビュー

https://github.com/docker-library/cassandra/blob/0e270a93b53119818f9c71fa273cda3a07d0bf5c/2.1/Dockerfile

# explicitly set user/group IDs
RUN groupadd -r cassandra --gid=999 && useradd -r -g cassandra --uid=999 cassandra

RUN groupadd -r sonarqube && useradd -r -g sonarqube sonarqube

Neo4jは拡張性が高く、堅牢なネイティブグラフデータベースです。

RUN addgroup -S neo4j && adduser -S -H -h /var/lib/neo4j -G neo4j neo4j

他にもいくつかのDockerfileを見つけましたが、どれも同じようにしています:addgroupとadduserを全て一行にまとめています。

以下、私は2行に分割されるようにneo4jを変更しました:これがちょうど良いように見えます。

RUN addgroup -S neo4j \
  && adduser -S -H -h /var/lib/neo4j -G neo4j neo4j

Dockerfilesのスニペットのレビュー - apt-get Install

https://github.com/nextcloud/docker/blob/424364e2e10a9d6e1a31e6659e2149aac1f1c772/12.0/apache/Dockerfile

ネクストクラウド:すべてのデータを安全に保管できます。ファイル、カレンダー、連絡先、メールなどにどのデバイスからでもアクセスし、共有することができます。

 RUN set -ex; \
    \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        rsync \
        bzip2 \
        busybox-static \
    ; \
    rm -rf /var/lib/apt/lists/*; \

私が見つけた中で一番読みやすかったapt-getの説明書です。

上のテキストと下の他の例を比較して、これがどのように優れているかを確認してください。

https://github.com/carlossg/docker-maven/blob/f581ea002e5d067deb6213c00a4d217297cad469/jdk-10-slim/Dockerfile。

Apache Mavenは、ソフトウェアのプロジェクト管理と理解のためのツールです。

RUN apt-get update && \
    apt-get install -y \
      curl procps \
  && rm -rf /var/lib/apt/lists/*   

一貫性のない、整列していないインデント。

https://github.com/docker-library/logstash/blob/606dfc2ead6902c11a0d809d7d66b192b87177e6/5/Dockerfile

Logstashは、イベントやログメッセージを収集、処理、転送するためのツールです。

# install plugin dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        apt-transport-https \
        libzmq5 \
    && rm -rf /var/lib/apt/lists/*

apt-get update &&apt-get install は一行で全て完了します。Neo4j ( 下の20行) は1行に1つの命令しかありません。どれだけ簡単に読めるか見てください。

https://github.com/docker-library/openjdk/blob/89851f0abc3a83cfad5248102f379d6a0bd3951a/6-jdk/Dockerfile

Javaは、並行型、クラスベース、オブジェクト指向の言語です。

RUN apt-get update && apt-get install -y --no-install-recommends \
        bzip2 \
        unzip \
        xz-utils \
    && rm -rf /var/lib/apt/lists/*

apt-get update &&apt-get install は一行ですべて完了します。他には1行に1つの命令しかないものもあります。これがどれだけ簡単に読めるかは以下をご覧ください。

https://github.com/neo4j/docker-neo4j-publish/blob/94477399f63ab99c035e50b46f642e791413dcaa/3.4.9/community/Dockerfile

Neo4jは拡張性が高く、堅牢なネイティブグラフデータベースです。

RUN apk add --no-cache --quiet \
    bash \
    curl \
    tini \
    su-exec \
    && curl --fail --silent --show-error --location --remote-name ${NEO4J_URI} \
    && echo "${NEO4J_SHA256}  ${NEO4J_TARBALL}" | sha256sum -csw - \
    && tar --extract --file ${NEO4J_TARBALL} --directory /var/lib \
    && mv /var/lib/neo4j-* /var/lib/neo4j \
    && rm ${NEO4J_TARBALL} \
    && mv /var/lib/neo4j/data /data \
    && chown -R neo4j:neo4j /data \
    && chmod -R 777 /data \
    && chown -R neo4j:neo4j /var/lib/neo4j \
    && chmod -R 777 /var/lib/neo4j \
    && ln -s /data /var/lib/neo4j/data \
    && apk del curl

1行に1つの命令を完璧に並べるているので非常に読みやすいです。

インストールする apk パッケージの一覧をアルファベット順に表示します。

Curl は 6 行目で使用され、最後の行で削除されました。もう必要ないので削除しました。

NEO4J_TARBALL}を10行目で抽出し、12行目で削除しました。

Dockerfilesのスニペットのレビュー - iniファイル

https://github.com/nextcloud/docker/blob/424364e2e10a9d6e1a31e6659e2149aac1f1c772/12.0/apache/Dockerfile

ネクストクラウドとは?

+すべてのデータを安全に保管します。ファイル、カレンダー、連絡先、メールなど、あらゆるデバイスからお好きな条件でアクセスし、共有することができます。

RUN { \
        echo 'opcache.enable=1'; \
        echo 'opcache.enable_cli=1'; \
        echo 'opcache.interned_strings_buffer=8'; \
        echo 'opcache.max_accelerated_files=10000'; \
        echo 'opcache.memory_consumption=128'; \
        echo 'opcache.save_comments=1'; \
        echo 'opcache.revalidate_freq=1'; \
    } > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
    \
    echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
    \
    echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
    \
    mkdir /var/www/data; \
    chown -R www-data:root /var/www; \
    chmod -R g=u /var/www

/ pro 最初の 7 行目のエコー設定を opcache-recommended.ini に追加し、非常にすっきりしました。
すっきりとした空行で 4 つの異なる目的をきれいに区切っています。

Dockerfiles のスニペットについてのレビュー

https://github.com/jenkinsci/docker/blob/587b2856cd225bb152c4abeeaaa24934c75aa460/Dockerfile

Jenkinsの継続的インテグレーションとデリバリーサーバ。

FROM openjdk:8-jdk

RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/*

ARG user=jenkins
ARG group=jenkins
ARG uid=1000
ARG gid=1000
ARG http_port=8080
ARG agent_port=50000

ENV JENKINS_HOME /var/jenkins_home
ENV JENKINS_SLAVE_AGENT_PORT ${agent_port}

'# Jenkins is run with user `jenkins`, uid = 1000
'# If you bind mount a volume from the host or a data container, 
'# ensure you use the same uid
RUN groupadd -g ${gid} ${group} \
    && useradd -d "$JENKINS_HOME" -u ${uid} -g ${gid} -m -s /bin/bash ${user}

'# for main web interface:
EXPOSE ${http_port}

'# will be used by attached slave agents:
EXPOSE ${agent_port}

プロの目線で見る:
1、ARGの名前はすべて小文字
2、関数でソートされた ARG 名: user + group; uid + guid; 2 ports
3、ENV はすべて大文字で名前を付ける。
4、2行でグループ追加とユーザー追加
5、useradd は groupadd と完全に一致。

Dockerfilesのスニペット - RUNのレビュー

https://github.com/docker-library/postgres/blob/88341a435106ea0c9a805ff305bf486f81f56e0c/11/Dockerfile

PostgreSQLオブジェクトリレーショナルデータベースシステム

ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin
ENV PGDATA /var/lib/postgresql/data
RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values)
VOLUME /var/lib/postgresql/data

ロングランは他の行の間に挟まれて潰されています。

改良版:

RUN mkdir -p "$PGDATA" \
    && chown -R postgres:postgres "$PGDATA" \
    && chmod 777 "$PGDATA" \
    # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values)

彼らのDockerfileの残りの部分は素晴らしいものです - 上のリンクを参照してください。彼らはまた、他のほとんどの人よりも多くのコメントを持っています。

Dockerfileのスニペットのレビュー - Sorted apt-get Install

https://hub.docker.com/_/httpd/ より

'# install httpd runtime dependencies
'# https://httpd.apache.org/docs/2.4/install.html#requirements
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libapr1 \
        libaprutil1 \
        libaprutil1-ldap \
        libapr1-dev \
        libaprutil1-dev \
        liblua5.2-0 \
        libnghttp2-14=$NGHTTP2_VERSION \
        libpcre++0 \
        libssl1.0.0=$OPENSSL_VERSION \
        libxml2 \
    && rm -r /var/lib/apt/lists/*

インストールするaptパッケージのリストをソートしました。

ソートされていない場合は以下のようになります。

RUN apt-get update 
&& apt-get install -y --no-install-recommends \
        libxml2 \
        libaprutil1 \
            libnghttp2-14=$NGHTTP2_VERSION \
        libapr1-dev \
      liblua5.2-0 \
        libaprutil1-dev \
        libpcre++0 \
        libapr1 \
        libssl1.0.0=$OPENSSL_VERSION \
    libaprutil1-ldap \
  && rm -r /var/lib/apt/lists/*

手でソートする必要はありません。エディタには、リストをハイライト表示して「SORT」をクリックするだけの機能があるでしょう。

開発中であっても、特定の libapr を見つけるのに役立つように、このようなリストをソートしておくと便利です。今は、データを見落とさないように上から下まで注意深く読まなければなりません。このようなことが一度でも起こった場合、ワンクリックでSORTを行うのは時間の投資になります。

デモのDockerfileを構築する

良いDockerfileと悪いDockerfileがどのように見えるか見てきましたが、自慢できるDockerfileを作ってみましょう。

あなたのDockerfileは、以下の手順を少なくとも一度は使用しなければなりません。

あなたのDockerfileはクールな完成したアプリケーションである必要はありません。これらのコマンドで可能な構文や機能を試しているだけです。

コマンドを実行し、ファイルを追加し、ワークディレクトリを作成、環境変数と引数を追加します。いくつかのポートを公開し、すべてにラベルを付け、ENTRYPOINTを用意します。ここでの目的は、コマンドに慣れることです。

https://hub.docker.com/explore/ で見つけたテキストスニペットをコピーしてください。

入力として使うソフトが違えば違うほど、学習の過程が面白くなります。

FROM 
COPY
ADD
RUN
LABEL
EXPOSE
ENVIRONMENT
ENTRYPOINT
VOLUME 
USER
WORKDIR
ARG

Dockerfileの概念

以下のテキストの目的は、あなたがどれだけDockerfileの用語を理解しているかをテストすることです。

このテキストにはDockerfileの概念を詰め込んだ文章が含まれています。

新しいことを教えるためのものではありません。

以下に書かれていることのほとんどを理解できれば、Dockerfileの用語に慣れていることになります。

以下の文章の約50%は以下からのものです。

https://docs.docker.com/glossary/

そのテキストは、より多くのDocker用語を含むように編集されました。

. . .

docker buildコマンドはDockerfileを使ってDockerイメージをビルドします。

Dockerfileは、Dockerイメージをビルドするために通常Linuxコマンドシェルで実行するすべてのLinuxコマンドを含むテキストファイルです。DockerはDockerfileから命令を読み取ることでイメージを構築することができます。

イメージは、分離されたコンテナ内でソフトウェアアプリケーションを実行するために必要なすべてのソフトウェアをレイヤー化したものです。イメージは実行されているわけではありません。

コンテナはdockerイメージのランタイムインスタンスです。イメージからコンテナを作成するには、docker runコマンドを使用することができます。

Dockerコンテナには、作成に使用したDockerイメージが含まれています。コンテナはミニ VM のようなものです。

Docker Hub - https://hub.docker.com - は、Docker イメージを保存するウェブサイトです。

レジストリとは、Dockerイメージのリポジトリが入っているWebサービスのことです。Docker Hubはレジストリです。

デフォルトのレジストリ - https://hub.docker.com - は、Docker Hubのブラウザを使ってアクセスするか、docker検索コマンドを使ってアクセスすることができます。

リポジトリはDockerイメージのセットです。リポジトリをレジストリサーバーにプッシュすることで、リポジトリを共有することができます - docker pushコマンドを使用します。この5つのチュートリアルのセットでは、このdocker pushコマンドは使いませんでした。

他にも1000人の人がdocker pushを使って1000枚のパブリックイメージを追加していました https://hub.docker.com

Dockerイメージはコンテナの基本です。イメージは、コンテナランタイム内で使用するためのルートファイルシステムの変更とそれに対応する実行パラメータのレイヤ化されたコレクションです。

docker runコマンドに追加の引数を指定せずにDockerfileを実行可能にしたい場合は、entrypoint、cmd、またはその両方を指定する必要があります。

名前付きボリュームとは、Dockerが管理しているボリュームのことです。

名前付きボリュームを作成する際には、フレンドリーなテキスト名を指定することができます。

匿名ボリュームは名前付きボリュームと似ていますが、匿名ボリュームの場合、時間の経過とともに同じボリュームを参照することが困難になることがあります。

Dockerfileベストプラクティスのまとめ

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

以下は、いくつかのDockerfileのベストプラクティスを一行でまとめたものです。

1、小さなビルドコンテキストを持つ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#understand-build-context
2、dockerignoreを使う ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#exclude-with-dockerignore
3、レイヤー数を最小化する... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers
4、複数行の引数を並べ替え ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#sort-multi-line-arguments
5、アルパインFROMを使用... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#from
6、ラベルを1枚追加 - 練習用に... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#label
7、長くて複雑な RUN 文を複数行に分割する - 上記の例を参照してください ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
8、任意のポートを公開する - 練習用に ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#expose
9、ENV変数の定義 ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#env
10、ADDとCOPYを使用して、その違いについて示す... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy
11、ボリュームの定義 ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#volume
12、デモテストユーザーの追加 - このチュートリアルのトップに例あり ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user
13、作業ディレクトリの作成 ... https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#workdir

フェーズ 1: 作成したデモDockerfileをレビューします。間違っていた点を修正します。

フェーズ 2: https://hub.docker.com/explore/ にアクセスします。

最初のパッケージ名: nginx をクリックしてください - そこにリストされている最初の Dockerfile を見つけてください - もう一度クリックして Dockerfile を確認してください。そして、それを簡単にスキャンして、ベストプラクティスが採用されているか、悪用されているかを確認してください。

また、上記で簡単に説明したきちんとしたプロスニペットも考慮してください。それらの Dockerfile を調べて、似たようなタイプの問題やベストプラクティスを見つけることができるかどうかを確認してください。

これを、時間のある限り多くの公式パッケージに対して行ってください。

また、そのウェブページの左上のボックスにお気に入りの Linux ソフトウェアの名前を入力してください。あなたの」ソフトウェアがどれだけうまくドッカー化されているかを調べてみてください。

あなたの番です。

この4つのチュートリアルで学んだことを職場で実践してみましょう。

これで、https://docs.docker.com/engine/reference/builder/ にある Dockerfile のリファレンスを読む準備ができました。

ここで述べられているほぼすべての概念に精通しているはずです。最初の3つのチュートリアルに基づいて、あなたはほとんどのDockerfileの説明を実際に実験してきました。

これで、非常に簡単に読めるようになったはずです。

今述べたことはすべて、以下のベストプラクティスにも同じように当てはまります。

https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/

これで、Alibaba Cloud Elastic Compute Service (ECS)インスタンス上でDockerコンテナを使ってクールなアプリを構築することができるようになりました。

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1