Kubernetes でコンテナ永続化はどうやる?そして、その前にcert-managerを使ったhttpsの自動化に必要なIngress Controllerで利用のNginxのロードバランサーで詰まる

夏が来れば 思い出す はるかな尾瀬 ~、どうも、ボクです。

前回、Kubernetes runコマンドで、コンテナ化アプリケーションのデプロイにトライし見事に失敗いたしました。

ts0818.hatenablog.com

⇧  前回のデプロイ失敗は、この記事の後半でも触れますが、Dockerのコンテナの仕様?が関係してたようです。

 

そして、全然関係ないですが、

www.slideshare.net

github.com

⇧  H2OっていうWebサーバが、奥一穂さんという方によって作成されたそうな、何でもNginxをはるかに上回るレスポンスを実現してるそうな。

時間があれば、構築を試してみたいですね。

 

そして、もう一つ関係ないですが、

qiita.com

⇧  Dockerのコマンドが新しくなってたみたいですね...旧いコマンドは非推奨になっていくような感じですかね...時の流れ~。

 

というわけで、今回は、Kubernetesにおいてのコンテナ永続化をする方法について調査していきたいと思います。

例のごとく、かなりまとまりのない内容、且つ、未解決となっているため、お時間のある方のみ、ご照覧ください。

 

2018年9月1日(土)追記:↓  ここから 

コンテナimageの記述がミスっていて、httpdApacheサーバ)が起動していないことが判明。ただいま、絶賛修正途中となっております。

2018年9月1日(土)追記:↑  ここまで 

 

 

コンテナ永続化って?Dockerの場合

そもそも、コンテナ永続化って?

コンテナが削除されたとしても、復元できるようにコンテナのデータを保存しておくことのようです。

で、Dockerの場合、Dockerの公式のドキュメント(日本語版)の用語集によりますと、

ボリュームとは特別に設計されたディレクトリであり、ユニオン・ファイル・システムを迂回し、複数のコンテナ内で使えます。ボリュームは永続的なデータを保管するために設計されており、コンテナのライフサイクルとは独立しています。

そのため、Docker はコンテナの削除時に、ボリュームを決して自動的に削除しません。そればかりか「ガベージ・コレクト」(ゴミ収集;garbage collect)ボリュームとして、コンテナからは参照できないようにもできます。

これは データ・ボリューム(data volume) とも呼ばれます。

ボリュームは、ホスト(host)、匿名(anonymous)、名前付き(named)の3種類です。

用語集 — Docker-docs-ja 17.06.Beta ドキュメント

⇧  ってなってますね。 

ファイルシステムに、コンテナのデータに関する情報をファイルとして保存しておくってことみたいですね。 

コンテナを削除したら、コンテナに対して書き込まれたあらゆるデータが削除されます。しかし、 データ・ボリューム (data volume) の保存内容は、コンテナと一緒に削除しません。

イメージ、コンテナ、ストレージ・ドライバの理解 — Docker-docs-ja 17.06.Beta ドキュメント

公式の図を引用させてもらうと、

f:id:ts0818:20180811132001p:plain

ということらしく、 

データ・ボリュームは Docker ホスト上のローカル・ストレージ領域の外に存在しており、ストレージ・ドライバの管理から独立して離れています。コンテナを削除したとしても、Docker ホスト上の共有データ・ボリュームに保管されたデータに対して、何ら影響はありません。

イメージ、コンテナ、ストレージ・ドライバの理解 — Docker-docs-ja 17.06.Beta ドキュメント

ということみたいです。

Docker ホストの中の「data」ディレクトリに保存されたコンテナのデータは、コンテナが削除されたとしても、残るということみたいです。

仮想マシンが停止して、Docker ホストが停止した場合も、「data」ディレクトリの内容は消えないって考えて良いのかしら?(でも、これ、不測の事態で、Docker ホストが削除されたら、「data」ディレクトリも消えるからコンテナ永続化ができないんじゃないのか...)

とりあえず、Dockerとしては、こんな感じでコンテナ永続化を実現してるらしいと。 

 

Kubernetesでのコンテナ永続化は?

んじゃあ、Docker以外のコンテナ runtimeにも対応しているKubernetesでは、コンテナ永続化は、どう実現してるのか?

thinkit.co.jp

⇧  上記サイト様によりますと、Kubernetesのリソースは5種類に大別され、

リソースの分類 内容
Workloadsリソース コンテナの実行に関するリソース
Discovery&LBリソース コンテナを外部公開するようなエンドポイントを提供するリソース
Config&Storageリソース 設定・機密情報・永続化ボリュームなどに関するリソース
Clusterリソース セキュリティやクォータなどに関するリソース
Metadataリソース リソースを操作する系統のリソース

この中の「Config & Storageリソース」が、コンテナ永続化にも関わってくるってことですかね。

「Config & Storageリソース」としては、

  1. Secret
    • ユーザ名やパスワードを別リソースとして定義しておき、Podから読み出すためのリソース
  2. ConfigMap
    • 設定情報などのKey-Valueで保持できるデータを保存しておくリソース
  3. PersistentVolumeClaim
    • 作成されたPersistentVolumeリソースの中からアサインするためのリソース

の3つがあるそうで、コンテナ永続化に関係してくるのは、

「3. PersistentVolumeClaim」になるそうです。

 

thinkit.co.jp

PersistentVolumeClaimを理解するために必要となるPersistentVolume、Volumeについても取り上げます。

KubernetesのConfig&Storageリソース(その2) | Think IT(シンクイット)

とあるように、「PersistentVolume」「Volume」の概念も押さえておく必要があるようです。 

Volume

Volumeは既存のボリューム(ホストの領域、NFS、Ceph、GCP Volume)などをYAML Manifestに直接指定することで利用可能にするものです。そのため、利用者が新規でボリュームを作成したり、既存のボリュームを削除したりといった操作を行うことはできません。また、YAML ManifestからVolumeリソースを作成するといった処理も行いません。

KubernetesのConfig&Storageリソース(その2) | Think IT(シンクイット)

PersistentVolume 

PersistentVolumeは、外部の永続ボリュームを提供するシステムと連携して、新規のボリュームの作成や、既存のボリュームの削除などを行うことが可能です。具体的には、YAML ManifestなどからPersistent Volumeリソースを別途作成する形になります。

KubernetesのConfig&Storageリソース(その2) | Think IT(シンクイット)

 

つまり、「Volume」のほうは、あらかじめ用意されているものを利用するしかなく、Dockerの「dataディレクトリみたいなイメージですかね?

一方、「PersistentVolume」のほうは、自分で作成できるみたいですね。

qiita.com

⇧  上記サイト様によりますと、 

kubernetes.io

⇧   Persistent Volume として利用できる外部ストレージは、Kubernetesの公式のサイトの「Volumes」に掲載されている一覧のものらしい。

On-disk files in a Container are ephemeral, which presents some problems for non-trivial applications when running in Containers. First, when a Container crashes, kubelet will restart it, but the files will be lost - the Container starts with a clean state. Second, when running Containers together in a Pod it is often necessary to share files between those Containers. The Kubernetes Volume abstraction solves both of these problems.

Volumes - Kubernetes

⇧  「Volumes」は、Kubernetesにおける2つの問題を解決してくるそうな。Google翻訳したところ、「Volumes」を使わない場合、

  1. Kubernetesで再起動が必要になった際に、コンテナのデータが失われる
  2. Pod内に複数のコンテナがある場合、コンテナ間でファイルの共有ができない

の問題に直面するようです。

で、Kubernetesで利用できる「Volumes」は、「Types of Volumes」で確認できます。

Types of Volumes

Kubernetes supports several types of Volumes:

Volumes - Kubernetes

ただ、クラウドGCPAWS、Azure)に登録していないと使えないものもあったりしそうですね。

 

Minikubeで構築した環境で、コンテナ永続化を実際に試してみる前に、コンテナimageの再作成

ありがたいことに、 Kubernetesのコンテナ永続化について、

qiita.com

⇧  上記サイト様が、Windowsでの構築手順を載っけてくれていました。

ただ、kubernetesにおけるyamlの記述の仕方がよく分からんですね。

初心者を慄かせるその大量のYAMLはよくwall of YAMLYAMLの壁)などと揶揄される.

Kubernetes YAMLの壁 | SOTA

Kubernetes Package Managerとは何か? KubernetesをKernelとみなすと複数のNodeインスタンスを束ねたClusterを1つのコンピューター,その上で動くコンテナはプロセスとみなすことができる.このような視点になるとHelmはCentOSにおけるYUMDebianにおけるAPTと同様の役割を果たす.

Kubernetes YAMLの壁 | SOTA

⇧  上記サイト様によりますと、 Kubernetesにもパッケージ管理ツールが存在するようで、 

  • Helm
  • ksonnet
  • kubecfg

なんかが有名のようです。

上記のパッケージ管理ツールでもYAMLの管理はできるようですが、

KustomizeYAMLファイルのDeclarative管理を推し進めReusabilityとCustomizabilityを高めるツールである.

KustomizeでKubernetes YAMLを管理する | SOTA

Declarative ConfigurationはKubernetesの重要な機能の一つだ.KubernetesユーザはKubernetes APIに対してあるべきDesiredな状態を宣言(Declare)することでKubernetesはその状態になるように動き続ける.

KustomizeでKubernetes YAMLを管理する | SOTA

⇧  さらに優れたツールとして期待されているのが、

  • Kustomize

というものらしいです。 

時間があれば、利用してみたいですね。

 

今回は、普通に、パッケージ管理ツールなどは利用せず、yamlファイルで。と思ったのですが、『Helm』を利用することになりました。詳しくは、後半で。

 

 

Kubernetesの公式のほうにも、「Concepts」>「Configuration」の項目の中に説明があるにはありますが、英語なのがしんどいですね。

kubernetes.io


reiki4040.hatenablog.com

⇧   上記サイト様が説明してくれていました。先人のお力を借りるということで。

 

その前に、せっかくなんで、コンテナimageを作り直して、JavaのAP(アプリケーション)サーバであるTomcat、WebサーバとしてApache Httpdを追加したいと思います。

 

ちなみに、JavaEE向けのTomcatである「Apache TomEE」なるものも存在するようですね、初めて知りました。

Apache TomEE (pronounced "Tommy") is the Java Enterprise Edition of Apache Tomcat (Tomcat + Java EE = TomEE) that combines several Java enterprise projects including Apache OpenEJB, Apache OpenWebBeansApache OpenJPAApache MyFaces and others. In October 2011, the project obtained certification by Oracle Corporation as a compatible implementation of the Java EE 6 Web Profile.

Apache TomEE - Wikipedia

JavaEEのAPサーバというと、

Java EEの機能を用いたアプリケーションを動作させるには、Java EEの仕様を実装した実行環境やライブラリが必要である。Java EE SDKには、Java EEに準拠したオープンソースアプリケーションサーバであるGlassFish Open Source Editionが同梱されている。GlassFish 4.0はJava EE 7の参照実装である。NetBeansEclipseといったJava開発ツールの多くもJava EEに対応している。

Java Platform, Enterprise Edition - Wikipedia

⇧  Wikipediaでも言ってるように、GlassFishが有名ですかね。

 

Webサーバは、

blog.apar.jp

⇧  上記サイト様を参考に、Apache Httpdソースコードからインストールする記述を追加していきたいと思います。

ちなみに、Brotliは、

Brotliは、Jyrki AlakuijalaとZoltán Szabadka英語版により開発されたオープンソースデータ圧縮ライブラリである。

Brotli - Wikipedia

対応しようとしてるWebサーバは、なんとApache Httpdのみっぽいですね。他は、周りが頑張ってる感じですかね。 

Apache HTTPサーバにおいては2.4.26で対応した。Brotliに対応するモジュールmod_brotliが追加されている 

Brotli - Wikipedia

Microsoft IISにおいては公式サポートも開発への取り組みもなされていないが、対応させるコミュニティモジュールが存在する。

Brotli - Wikipedia

nginxにおいては公式サポートも開発への取り組みもなされておらず、Googleの提供する ngx_brotliモジュールにより対応する。

Brotli - Wikipedia

 

すみません、脱線しました。 

edywrite.blogspot.com

qiita.com

 

⇧  Tomcat部分の記述は、上記サイト様を参考にさせていただきました。(Docker HubのOFFICIALなTomcat用のコンテナimageのためのDockerfileの記述が、UbuntuとかDebian向けっぽいですけど...CentOS向けの記述も欲しいですね )

Tomcatの「server.xml」をファイルとして保存しておきます。

「C:¥Users¥Toshinobu¥.minikube¥machines¥minikube¥minikube¥tomcat_conf」を作成し、配置しました。

f:id:ts0818:20180823221248p:plain

 

Apache_Httpd の設定ファイルを用意しておきます。

blog.apar.jp

⇧  毎回お世話になっている、あぱーブログさんの掲載してくださっている「http.conf」「http_ssl.conf」の内容をファイルとして保存しておきます。

「http.conf」のUserとgroupをapacheに変更し、TomcatAJP(Apache JServ Protocol)で接続するための設定を追記しました。

User damone
Group damone
User apache
Group apache
# Tomcatに連携
RewriteEngine on
ProxyPass   /  ajp://localhost:8002/

ajpのパスは、Tomcatの「server.xml」のajpについての記述部分に合わせます。

「C:¥Users¥Toshinobu¥.minikube¥machines¥minikube¥minikube¥httpd_config」を作成し、配置いたしました。

f:id:ts0818:20180820184204p:plain

そして、Dockerfileでのfirewalld(CentOS7で登場)の設定の仕方が分からず、

github.com

⇧  上記サイト様の「enforce-rule.sh」 を使わせていただくことに。「firewalld」でなく「iptables」を使っていくことになります。

「C:¥Users¥Toshinobu¥.minikube¥machines¥minikube¥minikube¥httpd_config」を作成し、配置いたしました。

f:id:ts0818:20180821132053p:plain

「firewalld」は内部的には、「iptables」を使っているそうな。

iptables」については、

blog.tiqwab.com

⇧  上記サイト様が詳しいです。

 

FROM centos:7.5.1804

#□□□ JAVAのインストール □□□#
# Java10用の変数(バージョン情報とか)
ARG jdk_version=10.0.2
ARG jdk_build_no=13
ARG jdk_hash_value=19aef61b38124481863b1413dce1855f
ARG jdk_rpm=jdk-${jdk_version}_linux-x64_bin.rpm

# Javaの環境変数のためのパス
ENV JAVA_HOME /usr/java/default

# yumのキャッシュをクリア
RUN yum clean all
# システム全体のアップデート
RUN yum -y update
# GPGキー(「GnuPG」(GNU Privacy Guard)という暗号化ソフトで生成される公開鍵。)のインストール
# ↑ パッケージが正しい配布先のものかどうかのチェックするもの
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
# wfetコマンドをインストール
RUN yum -y install wget

# JDK10のインストール
RUN wget -q \
         --no-check-certificate \
         --no-cookies \
         --header "Cookie: oraclelicense=accept-securebackup-cookie" \
         http://download.oracle.com/otn-pub/java/jdk/${jdk_version}+${jdk_build_no}/${jdk_hash_value}/${jdk_rpm} && \
    rpm -ivh ${jdk_rpm}


#□□□ Tomcatのインストール □□□#
# Tomcat9用の変数(バージョン情報とか)
ARG tom_magor=9
ARG tom_version=9.0.11

# Tomcatの環境変数のためのパス
ENV CATALINA_HOME /usr/local/tomcat-${tom_version}

# 環境変数に追加するためのパスを用意
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

# Javaのクラスパスを用意
ENV CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/common/lib

# Javaのパス、Javaのクラスパス、Tomcatのパスを環境変数に追加
RUN export JAVA_HOME PATH CLASSPATH CATALINA_HOME

# Tomcatのダウンロード、展開(解凍)
RUN wget http://www-eu.apache.org/dist/tomcat/tomcat-${tom_magor}/v${tom_version}/bin/apache-tomcat-${tom_version}.tar.gz && \
    tar -xvzf apache-tomcat-${tom_version}.tar.gz && \
    mv apache-tomcat-${tom_version} /usr/local/tomcat-${tom_version}

# ユーザー「tomcat」を作成
RUN useradd -s /sbin/nologin tomcat

# Apache Tomcatの所有者を、ユーザー「tomcat」に設定
RUN chown -R tomcat:tomcat /usr/local/tomcat-${tom_version}

# host(Windows)側に用意したTomcatのserver.xmlを、コンテナ側にコピー
ADD ./tomcat_conf/server.xml /usr/local/tomcat-${tom_version}/conf/server.xml

# 起動スクリプト用
RUN cp /usr/local/tomcat-${tom_version}/bin/catalina.sh /etc/init.d/tomcat-${tom_version}
RUN chmod 775 /etc/init.d/tomcat-${tom_version}


#□□□ Apache Httpdのインストール □□□#
# Apache Httpdのインストールに必要な基本コマンド、開発ツールのインストール
RUN yum groups mark convert
RUN yum -y groupinstall base
RUN yum -y groupinstall development
RUN yum -y update

# Nghttp2に必要なライブラリのインストール
RUN yum -y install openssl-devel jansson-devel libev-devel c-ares-devel

#□□ Nghttp2のインストール □□#
# Nghttp2用の変数(バージョン情報とか)
ARG nghttp2_version=1.32.0

# Nghttp2最新版の情報 -> https://github.com/tatsuhiro-t/nghttp2/releases/latest
# Nghttp2のダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://github.com/nghttp2/nghttp2/releases/download/v${nghttp2_version}/nghttp2-${nghttp2_version}.tar.gz && \
    tar xvzf nghttp2-${nghttp2_version}.tar.gz

# Nghttp2をコンパイルしてインストール
# HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib 以下にインストールされます。
# Nghttp2 関連のコマンドは /usr/local/bin 以下にインストールされます。
RUN cd /usr/local/src/nghttp2-${nghttp2_version}/ && \
    ./configure -enable-app && \
    make && \
    make install

#□□ Brotliのインストール □□#
# Brotli用の変数(バージョン情報とか)
ARG brotli_version=1.0.5

# Brotliのコンパイルに必要なcmakeのインストール
RUN yum -y install cmake

# Brotli最新版の情報 -> https://github.com/google/brotli/releases/latest
# Brotliのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://github.com/google/brotli/archive/v${brotli_version}.tar.gz && \
    tar xvzf v${brotli_version}.tar.gz

# Brotliをコンパイルしてインストール
# Brotli のライブラリが /usr/local/lib 以下にインストールされます。
RUN cd /usr/local/src/brotli-${brotli_version}/ && \
    mkdir out && cd out && \
    ../configure-cmake && \
    make && \
    make test && \
    make install

# ライブラリへのパス追加
RUN echo /usr/local/lib > /etc/ld.so.conf.d/usr-local-lib.conf
RUN ldconfig

#□□  curlの最新版のインストール □□#
# curl用の変数(バージョン情報とか)
ARG curl_version=7.61.0

# curl最新版の情報 -> https://curl.haxx.se/changes.html
# curlのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://curl.haxx.se/download/curl-${curl_version}.tar.gz && \
    tar xvzf curl-${curl_version}.tar.gz

# curlをコンパイルしてインストール
RUN cd /usr/local/src/curl-${curl_version}/ && \
    ./configure && \
    make && \
    make install

# Apche httpdのコンパイルに必要なパッケージのインストール
RUN yum -y install pcre-devel expat-devel
# APR、APRUの最新版の情報 -> http://apr.apache.org/
#□□  APR(Apache Portable Runtime)の最新版のインストール □□#
# APR(Apache Portable Runtime)用の変数(バージョン情報とか)
ARG apr_version=1.6.3

# ARPのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//apr/apr-${apr_version}.tar.gz && \
    tar xvzf apr-${apr_version}.tar.gz

# APRをコンパイルしてインストール
RUN cd /usr/local/src/apr-${apr_version}/ && \
    ./configure && \
    make && \
    make install

#□□  APR-util(Apache Portable Runtime Utility)の最新版のインストール □□#
# APR-util(Apache Portable Runtime Utility)用の変数(バージョン情報とか)
ARG apr_util_version=1.6.1

# ARP-utilのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//apr/apr-util-${apr_util_version}.tar.gz && \
    tar xvzf apr-util-${apr_util_version}.tar.gz

# APR-utilをコンパイルしてインストール
RUN cd /usr/local/src/apr-util-${apr_util_version}/ && \
    ./configure --with-apr=/usr/local/apr && \
    make && \
    make install

# Apache httpd用の変数(バージョン情報とか)
ARG httpd_version=2.4.34

# Apache httpdのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//httpd/httpd-${httpd_version}.tar.gz && \
    tar xvzf httpd-${httpd_version}.tar.gz

# Apache httpdをコンパイルしてインストール
RUN cd /usr/local/src/httpd-${httpd_version}/ && \
    ./configure \
        --enable-http2 \
        --enable-brotli \
        --with-brotli=/usr/local/lib \
        --enable-ssl \
        --enable-md \
        --with-apr=/usr/local/apr \
        --with-apr-util=/usr/local/apr \
        --enable-so \
        --enable-mods-shared=all \
        --enable-mpms-shared=all && \
    make && \
    make install

# Apache Httpdの設定ファイルのバックアップ
RUN mv -i /usr/local/apache2/conf/httpd.conf /usr/local/apache2/conf/httpd.conf.org
RUN mv -i /usr/local/apache2/conf/extra/httpd-ssl.conf /usr/local/apache2/conf/extra/httpd-ssl.conf.org

# host(Windows)側に用意したhttpdの設定ファイルを、コンテナ側にコピー
# Dockerfile内で利用の場合、docker cpはADDになる
ADD ./httpd_config/httpd.conf /usr/local/apache2/conf/httpd.conf
ADD ./httpd_config/httpd_ssl.conf /usr/local/apache2/conf/extra/httpd_ssl.conf

# apache 設定(httpd.confでapacheユーザー、apacheグループを設定してるので割愛)
# RUN chown -R apache:apache /var/www/html/

# iptablesのインストール
RUN yum -y install iptables

# host(Windows)側に用意したiptablesの設定ファイルを、コンテナ側にコピー
ADD ./firewall/enforce_rules.sh /bin

# iptablesの設定。(HTTP(80/tcp) と HTTPS(443/tcp)の開放)
ENV CHAIN_NAME "CONTAINER-FIREWALL"
ENV ACCEPT_PORT "80,443"

# iptables、httpd、Tomcatの起動スクリプトの作成
RUN echo -e $'sh /bin/firewall/enforce_rules.sh\n\
              /etc/init.d/httpd start\n\
              /etc/init.d/tomcat-${tom_version} start\n\
              /bin/bash' > /startService.sh

# 起動スクリプトの権限
RUN chmod o+x /startService.sh

# httpd、Tomcatの起動スクリプトの作成
RUN echo -e "/etc/init.d/httpd start\n/etc/init.d/tomcat-${tom_version} start\n/bin/bash" > /startService.sh

# 公開ポート(apache:80,tomcat:8888で空けてる)
EXPOSE 80 8888
    
CMD ["catalina.sh", "run"]

上記のDockerfileでコンテナimageを作成はできたっぽい(この後、docker buildして、successfullyとかなったので)ですが、起動スクリプトが動くか微妙です...。

 

2018年9月1日(土)追記:  ↓  ここから

iptablesの設定ファイルがコピーできてなかったり、起動スクリプトで、Apache Httpdの部分が誤っていました。

というわけで、新たにホスト側に、httpdをサービス起動するための設定ファイルを用意。「C:¥Users¥Toshinobu¥.minikube¥machines¥minikube¥minikube¥httpd_config」に「httpd.service」を作成。

f:id:ts0818:20180901202215p:plain

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
 
[Service]
Type=forking
ExecStart=/usr/local/apache2/bin/apachectl start
ExecReload=/usr/local/apache2/bin/apachectl graceful
ExecStop=/usr/local/apache2/bin/apachectl stop
 
[Install]
WantedBy=multi-user.target   

で、Dockerfileを修正。

FROM centos:7.5.1804

#□□□ JAVAのインストール □□□#
# Java10用の変数(バージョン情報とか)
ARG jdk_version=10.0.2
ARG jdk_build_no=13
ARG jdk_hash_value=19aef61b38124481863b1413dce1855f
ARG jdk_rpm=jdk-${jdk_version}_linux-x64_bin.rpm

# Javaの環境変数のためのパス
ENV JAVA_HOME /usr/java/default

# yumのキャッシュをクリア
RUN yum clean all
# システム全体のアップデート
RUN yum -y update
# GPGキー(「GnuPG」(GNU Privacy Guard)という暗号化ソフトで生成される公開鍵。)のインストール
# ↑ パッケージが正しい配布先のものかどうかのチェックするもの
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
# wfetコマンドをインストール
RUN yum -y install wget

# JDK10のインストール
RUN wget -q \
         --no-check-certificate \
         --no-cookies \
         --header "Cookie: oraclelicense=accept-securebackup-cookie" \
         http://download.oracle.com/otn-pub/java/jdk/${jdk_version}+${jdk_build_no}/${jdk_hash_value}/${jdk_rpm} && \
    rpm -ivh ${jdk_rpm}


#□□□ Tomcatのインストール □□□#
# Tomcat9用の変数(バージョン情報とか)
ARG tom_magor=9
ARG tom_version=9.0.11

# Tomcatの環境変数のためのパス
ENV CATALINA_HOME /usr/local/tomcat-${tom_version}

# 環境変数に追加するためのパスを用意
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

# Javaのクラスパスを用意
ENV CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/common/lib

# Javaのパス、Javaのクラスパス、Tomcatのパスを環境変数に追加
RUN export JAVA_HOME PATH CLASSPATH CATALINA_HOME

# Tomcatのダウンロード、展開(解凍)
RUN wget http://www-eu.apache.org/dist/tomcat/tomcat-${tom_magor}/v${tom_version}/bin/apache-tomcat-${tom_version}.tar.gz && \
    tar -xvzf apache-tomcat-${tom_version}.tar.gz && \
    mv apache-tomcat-${tom_version} /usr/local/tomcat-${tom_version}

# ユーザー「tomcat」を作成
RUN useradd -s /sbin/nologin tomcat

# Apache Tomcatの所有者を、ユーザー「tomcat」に設定
RUN chown -R tomcat:tomcat /usr/local/tomcat-${tom_version}

# host(Windows)側に用意したTomcatのserver.xmlを、コンテナ側にコピー
ADD ./tomcat_conf/server.xml /usr/local/tomcat-${tom_version}/conf/server.xml

# 起動スクリプト用
RUN cp /usr/local/tomcat-${tom_version}/bin/catalina.sh /etc/init.d/tomcat-${tom_version}
RUN chmod 775 /etc/init.d/tomcat-${tom_version}


#□□□ Apache Httpdのインストール □□□#
# Apache Httpdのインストールに必要な基本コマンド、開発ツールのインストール
RUN yum groups mark convert
RUN yum -y groupinstall base
RUN yum -y groupinstall development
RUN yum -y update

# Nghttp2に必要なライブラリのインストール
RUN yum -y install openssl-devel jansson-devel libev-devel c-ares-devel

#□□ Nghttp2のインストール □□#
# Nghttp2用の変数(バージョン情報とか)
ARG nghttp2_version=1.32.0

# Nghttp2最新版の情報 -> https://github.com/tatsuhiro-t/nghttp2/releases/latest
# Nghttp2のダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://github.com/nghttp2/nghttp2/releases/download/v${nghttp2_version}/nghttp2-${nghttp2_version}.tar.gz && \
    tar xvzf nghttp2-${nghttp2_version}.tar.gz

# Nghttp2をコンパイルしてインストール
# HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib 以下にインストールされます。
# Nghttp2 関連のコマンドは /usr/local/bin 以下にインストールされます。
RUN cd /usr/local/src/nghttp2-${nghttp2_version}/ && \
    ./configure -enable-app && \
    make && \
    make install

#□□ Brotliのインストール □□#
# Brotli用の変数(バージョン情報とか)
ARG brotli_version=1.0.5

# Brotliのコンパイルに必要なcmakeのインストール
RUN yum -y install cmake

# Brotli最新版の情報 -> https://github.com/google/brotli/releases/latest
# Brotliのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://github.com/google/brotli/archive/v${brotli_version}.tar.gz && \
    tar xvzf v${brotli_version}.tar.gz

# Brotliをコンパイルしてインストール
# Brotli のライブラリが /usr/local/lib 以下にインストールされます。
RUN cd /usr/local/src/brotli-${brotli_version}/ && \
    mkdir out && cd out && \
    ../configure-cmake && \
    make && \
    make test && \
    make install

# ライブラリへのパス追加
RUN echo /usr/local/lib > /etc/ld.so.conf.d/usr-local-lib.conf
RUN ldconfig

#□□  curlの最新版のインストール □□#
# curl用の変数(バージョン情報とか)
ARG curl_version=7.61.0

# curl最新版の情報 -> https://curl.haxx.se/changes.html
# curlのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://curl.haxx.se/download/curl-${curl_version}.tar.gz && \
    tar xvzf curl-${curl_version}.tar.gz

# curlをコンパイルしてインストール
RUN cd /usr/local/src/curl-${curl_version}/ && \
    ./configure && \
    make && \
    make install

# Apche httpdのコンパイルに必要なパッケージのインストール
RUN yum -y install pcre-devel expat-devel
# APR、APRUの最新版の情報 -> http://apr.apache.org/
#□□  APR(Apache Portable Runtime)の最新版のインストール □□#
# APR(Apache Portable Runtime)用の変数(バージョン情報とか)
ARG apr_version=1.6.3

# ARPのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//apr/apr-${apr_version}.tar.gz && \
    tar xvzf apr-${apr_version}.tar.gz

# APRをコンパイルしてインストール
RUN cd /usr/local/src/apr-${apr_version}/ && \
    ./configure && \
    make && \
    make install

#□□  APR-util(Apache Portable Runtime Utility)の最新版のインストール □□#
# APR-util(Apache Portable Runtime Utility)用の変数(バージョン情報とか)
ARG apr_util_version=1.6.1

# ARP-utilのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//apr/apr-util-${apr_util_version}.tar.gz && \
    tar xvzf apr-util-${apr_util_version}.tar.gz

# APR-utilをコンパイルしてインストール
RUN cd /usr/local/src/apr-util-${apr_util_version}/ && \
    ./configure --with-apr=/usr/local/apr && \
    make && \
    make install

# Apache httpd用の変数(バージョン情報とか)
ARG httpd_version=2.4.34

# Apache httpdのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//httpd/httpd-${httpd_version}.tar.gz && \
    tar xvzf httpd-${httpd_version}.tar.gz

# Apache httpdをコンパイルしてインストール
RUN cd /usr/local/src/httpd-${httpd_version}/ && \
    ./configure \
        --enable-http2 \
        --enable-brotli \
        --with-brotli=/usr/local/lib \
        --enable-ssl \
        --enable-md \
        --with-apr=/usr/local/apr \
        --with-apr-util=/usr/local/apr \
        --enable-so \
        --enable-mods-shared=all \
        --enable-mpms-shared=all && \
    make && \
    make install

# Apache Httpdの設定ファイルのバックアップ
RUN mv -i /usr/local/apache2/conf/httpd.conf /usr/local/apache2/conf/httpd.conf.org
RUN mv -i /usr/local/apache2/conf/extra/httpd-ssl.conf /usr/local/apache2/conf/extra/httpd-ssl.conf.org

# host(Windows)側に用意したhttpdの設定ファイルを、コンテナ側にコピー
# Dockerfile内で利用の場合、docker cpはADDになる
ADD ./httpd_config/httpd.conf /usr/local/apache2/conf/httpd.conf
ADD ./httpd_config/httpd_ssl.conf /usr/local/apache2/conf/extra/httpd_ssl.conf

# apache 設定(httpd.confで、apacheユーザー、apacheグループを設定してるので、割愛)
# RUN chown -R apache:apache /var/www/html/

# host(Windows)側に用意したhttpdをサービスとして起動するための設定ファイルを、コンテナ側にコピー
ADD ./httpd_config/httpd.service /etc/systemd/system/httpd.service

# iptablesのインストール
RUN yum -y install iptables

# host(Windows)側に用意したiptablesの設定ファイルを、コンテナ側にコピー
ADD ./firewall/enforce_rules.sh /bin/firewall/enforce_rules.sh

# iptablesの設定。(HTTP(80/tcp) と HTTPS(443/tcp)の開放)
ENV CHAIN_NAME "CONTAINER-FIREWALL"
ENV ACCEPT_PORT "80,443"

# iptables、httpd、Tomcatの起動スクリプトの作成
RUN echo -e $'sh /bin/firewall/enforce_rules.sh\n\
systemctl daemon-reload\n\
systemctl start httpd\n\
systemctl enable httpd\n\
/etc/init.d/tomcat-${tom_version} start\n\
/bin/bash' > /startService.sh

# スクリプトの権限
RUN chmod o+x /startService.sh

# 公開ポート(apache:80,tomcat:8888で空けてる)
EXPOSE 80 8888
    
CMD /startService.sh   

という感じで修正しましたが、Dockerのコンテナでは、httpdなどで利用されるsystemctlコマンドが許可されないという問題もあるため、コンテナにログイン後にsystemctlコマンドが利用できない問題が解決できていない状態です。

そして、httpdの起動を確認できてないので、また、修正が入るかもです、申し訳ないです。

2018年9月1日(土)追記:  ↑  ここまで

 

2018年9月9日(日)追記:  ↓  ここから

Apache Httpdにmod_systemdっていうモジュールをインストールすることで、systemctlコマンドが利用できるようになるのだとか。

systemd.unit(5) - Linux manual page のページにある、「systemd.service(5)」っていうリンクのページにあるように、httpdをサービスとして起動する場合、サービスのプロセスのタイプとして何種類かあり、その中の1つのdbusが、Dockerでは、エラーになってしまうらしい。

mod_systemdモジュールは、このサービスのプロセスのタイプが、notifyというものになるそうです。

FROM centos:7.5.1804

#□□□ JAVAのインストール □□□#
# Java10用の変数(バージョン情報とか)
ARG jdk_version=10.0.2
ARG jdk_build_no=13
ARG jdk_hash_value=19aef61b38124481863b1413dce1855f
ARG jdk_rpm=jdk-${jdk_version}_linux-x64_bin.rpm

# Javaの環境変数のためのパス
ENV JAVA_HOME /usr/java/default

# yumのキャッシュをクリア
RUN yum clean all
# システム全体のアップデート
RUN yum -y update
# GPGキー(「GnuPG」(GNU Privacy Guard)という暗号化ソフトで生成される公開鍵。)のインストール
# ↑ パッケージが正しい配布先のものかどうかのチェックするもの
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
# wfetコマンドをインストール
RUN yum -y install wget

# JDK10のインストール
RUN wget -q \
         --no-check-certificate \
         --no-cookies \
         --header "Cookie: oraclelicense=accept-securebackup-cookie" \
         http://download.oracle.com/otn-pub/java/jdk/${jdk_version}+${jdk_build_no}/${jdk_hash_value}/${jdk_rpm} && \
    rpm -ivh ${jdk_rpm}


#□□□ Tomcatのインストール □□□#
# Tomcat9用の変数(バージョン情報とか)
ARG tom_magor=9
ARG tom_version=9.0.11

# Tomcatの環境変数のためのパス
ENV CATALINA_HOME /usr/local/tomcat-${tom_version}

# 環境変数に追加するためのパスを用意
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

# Javaのクラスパスを用意
ENV CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/common/lib

# Javaのパス、Javaのクラスパス、Tomcatのパスを環境変数に追加
RUN export JAVA_HOME PATH CLASSPATH CATALINA_HOME

# Tomcatのダウンロード、展開(解凍)
RUN wget http://www-eu.apache.org/dist/tomcat/tomcat-${tom_magor}/v${tom_version}/bin/apache-tomcat-${tom_version}.tar.gz && \
    tar -xvzf apache-tomcat-${tom_version}.tar.gz && \
    mv apache-tomcat-${tom_version} /usr/local/tomcat-${tom_version}

# ユーザー「tomcat」を作成
RUN useradd -s /sbin/nologin tomcat

# Apache Tomcatの所有者を、ユーザー「tomcat」に設定
RUN chown -R tomcat:tomcat /usr/local/tomcat-${tom_version}

# host(Windows)側に用意したTomcatのserver.xmlを、コンテナ側にコピー
ADD ./tomcat_conf/server.xml /usr/local/tomcat-${tom_version}/conf/server.xml

# 起動スクリプト用
RUN cp /usr/local/tomcat-${tom_version}/bin/catalina.sh /etc/init.d/tomcat-${tom_version}
RUN chmod 775 /etc/init.d/tomcat-${tom_version}


#□□□ Apache Httpdのインストール □□□#
# Apache Httpdのインストールに必要な基本コマンド、開発ツールのインストール
RUN yum groups mark convert
RUN yum -y groupinstall base
RUN yum -y groupinstall development
RUN yum -y update

# Nghttp2に必要なライブラリのインストール
RUN yum -y install openssl-devel jansson-devel libev-devel c-ares-devel

#□□ Nghttp2のインストール □□#
# Nghttp2用の変数(バージョン情報とか)
ARG nghttp2_version=1.32.0

# Nghttp2最新版の情報 -> https://github.com/tatsuhiro-t/nghttp2/releases/latest
# Nghttp2のダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://github.com/nghttp2/nghttp2/releases/download/v${nghttp2_version}/nghttp2-${nghttp2_version}.tar.gz && \
    tar xvzf nghttp2-${nghttp2_version}.tar.gz

# Nghttp2をコンパイルしてインストール
# HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib 以下にインストールされます。
# Nghttp2 関連のコマンドは /usr/local/bin 以下にインストールされます。
RUN cd /usr/local/src/nghttp2-${nghttp2_version}/ && \
    ./configure -enable-app && \
    make && \
    make install

#□□ Brotliのインストール □□#
# Brotli用の変数(バージョン情報とか)
ARG brotli_version=1.0.5

# Brotliのコンパイルに必要なcmakeのインストール
RUN yum -y install cmake

# Brotli最新版の情報 -> https://github.com/google/brotli/releases/latest
# Brotliのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://github.com/google/brotli/archive/v${brotli_version}.tar.gz && \
    tar xvzf v${brotli_version}.tar.gz

# Brotliをコンパイルしてインストール
# Brotli のライブラリが /usr/local/lib 以下にインストールされます。
RUN cd /usr/local/src/brotli-${brotli_version}/ && \
    mkdir out && cd out && \
    ../configure-cmake && \
    make && \
    make test && \
    make install

# ライブラリへのパス追加
RUN echo /usr/local/lib > /etc/ld.so.conf.d/usr-local-lib.conf
RUN ldconfig

#□□  curlの最新版のインストール □□#
# curl用の変数(バージョン情報とか)
ARG curl_version=7.61.0

# curl最新版の情報 -> https://curl.haxx.se/changes.html
# curlのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget https://curl.haxx.se/download/curl-${curl_version}.tar.gz && \
    tar xvzf curl-${curl_version}.tar.gz

# curlをコンパイルしてインストール
RUN cd /usr/local/src/curl-${curl_version}/ && \
    ./configure && \
    make && \
    make install

# Apche httpdのコンパイルに必要なパッケージのインストール
RUN yum -y install pcre-devel expat-devel
# APR、APRUの最新版の情報 -> http://apr.apache.org/
#□□  APR(Apache Portable Runtime)の最新版のインストール □□#
# APR(Apache Portable Runtime)用の変数(バージョン情報とか)
ARG apr_version=1.6.3

# ARPのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//apr/apr-${apr_version}.tar.gz && \
    tar xvzf apr-${apr_version}.tar.gz

# APRをコンパイルしてインストール
RUN cd /usr/local/src/apr-${apr_version}/ && \
    ./configure && \
    make && \
    make install

#□□  APR-util(Apache Portable Runtime Utility)の最新版のインストール □□#
# APR-util(Apache Portable Runtime Utility)用の変数(バージョン情報とか)
ARG apr_util_version=1.6.1

# ARP-utilのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//apr/apr-util-${apr_util_version}.tar.gz && \
    tar xvzf apr-util-${apr_util_version}.tar.gz

# APR-utilをコンパイルしてインストール
RUN cd /usr/local/src/apr-util-${apr_util_version}/ && \
    ./configure --with-apr=/usr/local/apr && \
    make && \
    make install

# Apache httpd用の変数(バージョン情報とか)
ARG httpd_version=2.4.34

# Apache httpdのダウンロードと展開(解凍)
RUN cd /usr/local/src/ && \
    wget http://www-us.apache.org/dist//httpd/httpd-${httpd_version}.tar.gz && \
    tar xvzf httpd-${httpd_version}.tar.gz

# Apache httpdをコンパイルしてインストール
RUN cd /usr/local/src/httpd-${httpd_version}/ && \
    ./configure \
        --enable-http2 \
        --enable-brotli \
        --with-brotli=/usr/local/lib \
        --enable-ssl \
        --enable-md \
        --with-apr=/usr/local/apr \
        --with-apr-util=/usr/local/apr \
        --enable-so \
        --enable-mods-shared=all \
        --enable-mpms-shared=all \
        --enable-proxy \
        --enable-proxy-ajp \
        --enable-headers && \
    make && \
    make install

# Apache Httpdの設定ファイルのバックアップ
RUN mv -i /usr/local/apache2/conf/httpd.conf /usr/local/apache2/conf/httpd.conf.org
RUN mv -i /usr/local/apache2/conf/extra/httpd-ssl.conf /usr/local/apache2/conf/extra/httpd-ssl.conf.org

# host(Windows)側に用意したhttpdの設定ファイルを、コンテナ側にコピー
# Dockerfile内で利用の場合、docker cpはADDになる
ADD ./httpd_config/httpd.conf /usr/local/apache2/conf/httpd.conf
ADD ./httpd_config/httpd_ssl.conf /usr/local/apache2/conf/extra/httpd_ssl.conf

# apache 設定(httpd.confで、apacheユーザー、apacheグループを設定してるので、割愛)
# RUN chown -R apache:apache /var/www/html/

# apxs(APache eXtenSion tool)を含むhttpd-develのインストール
RUN yum -y install httpd-devel

# mod_systemd.cのコンパイルに必要なライブラリのインストール
RUN yum -y install systemd-devel

# Apache Httpdのモジュール、mod_systemd.cのダウンロード、コンパイル
RUN cd /usr/local/src/httpd-${httpd_version}/modules/arch/unix && \
    wget "https://svn.apache.org/viewvc/httpd/httpd/trunk/modules/arch/unix/mod_systemd.c?view=co" -O mod_systemd.c && \
    /usr/local/apache2/bin/apxs -c mod_systemd.c -I /usr/include/systemd/sd-daemon.h && \
    libtool \
      --silent \
      --mode=compile gcc -std=gnu99 -prefer-pic -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong \
      --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_LARGEFILE64_SOURCE -DLINUX -D_REENTRANT -D_GNU_SOURCE -pthread -I/usr/local/apache2/include -I/usr/local/apache2/include -I/usr/local/apache2/include -I/usr/local/apr/include/apr-1 -c -o mod_systemd.lo mod_systemd.c && \
    touch mod_systemd.slo && \
    libtool \
      --silent \
      --mode=link gcc -std=gnu99 -Wl,-z,relro,-z,now,-L/usr/lib64 -o mod_systemd.la -rpath /usr/local/apache2/modules -module -avoid-version mod_systemd.lo && \
    libtool \
      --silent \
      --mode=link gcc -std=gnu99 -Wl,-z,relro,-z,now,-L/usr/lib64 -o mod_systemd.la -rpath /usr/local/apache2/modules -module -avoid-version mod_systemd.lo -lsystemd-daemon

# mod_systemdのインストール
RUN cd /usr/local/src/httpd-${httpd_version}/modules/arch/unix && \
    /usr/local/apache2/bin/apxs -i -a -n systemd mod_systemd.la
# apache httpdのモジュールを共有ライブラリとして登録
RUN echo /usr/local/apache2/modules >> /etc/ld.so.conf
# スーパーユーザーに切り替え
USER root
# 共有ライブラリの依存関係情報を更新 >RUN ldconfig # host(Windows)側に用意したhttpdをサービスとして起動するための設定ファイルを、コンテナ側にコピー ADD ./httpd_config/httpd.service /etc/systemd/system/httpd.service # iptablesのインストール RUN yum -y install iptables # host(Windows)側に用意したiptablesの設定ファイルを、コンテナ側にコピー ADD ./firewall/enforce_rules.sh /bin/firewall/enforce_rules.sh # iptablesの設定。(HTTP(80/tcp) と HTTPS(443/tcp)の開放) ENV CHAIN_NAME "CONTAINER-FIREWALL" ENV ACCEPT_PORT "80,443" # iptables、httpd、Tomcatの起動スクリプトの作成 RUN echo -e $'sh /bin/firewall/enforce_rules.sh\n\ systemctl daemon-reload\n\ systemctl start httpd\n\ systemctl enable httpd\n\ /etc/init.d/tomcat-9.0.11 start\n\ /bin/bash' > /startService.sh # スクリプトの権限 RUN chmod o+x /startService.sh # 公開ポート(apache:80,tomcat:8888で空けてる) EXPOSE 80 8888 CMD /startService.sh

httpd.serviceファイルの方は、

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
 
[Service]
Type=forking
ExecStart=/usr/local/apache2/bin/apachectl start
ExecReload=/usr/local/apache2/bin/apachectl graceful
ExecStop=/usr/local/apache2/bin/apachectl stop
 
[Install]
WantedBy=multi-user.target   [Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)
 
[Service]
Type=notify
ExecStart=/usr/local/apache2/bin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/local/bin/httpd $OPTIONS -k graceful
ExecStop=/bin/kill -WINCH ${MAINPID}

KillSignal=SIGCONT
PrivateTmp=true

[Install]
WantedBy=multi-user.target

と修正。

libtoolの部分の呪文みたいな部分は、

libtool は静的ライブラリや共有ライブラリの コンパイル・リンク・インストール・アンインストールの複雑さを簡略化する。 異なるプラットフォームそれぞれで、完全な機能を 統一的なインターフェースを介して使用することができ、 プラットフォーム固有の厄介な癖はプログラマーから隠蔽される。

Man page of LIBTOOL

⇧  とあるように、良しなに取り計らってくれるそうです。隠蔽されるから、エラー起きた場合、原因が分からなくなりそうですが...

今回は、gccというコンパイラを利用している感じですが、複雑そうに見えるんですがね....

ちなみに、2018年9月9日(日)時点では、

GCC, the GNU Compiler Collection - GNU Project - Free Software Foundation (FSF)

⇧  gccの最新バージョンは、8.2らしいです。

gcc.gnu.org

⇧  gcc(バージョン8.2)のオプションの詳細については、上記サイト様へ。

今回使ってるgccのオプション

オプション 意味
-std C標準のバージョンを設定。デフォルト(何も指定しないと、-std=gnu11 が暗黙的に設定されるようです)
-O2 最適化を行う
-g コンパイル,リンク時にDEBUG情報を付加する
-pipe 様々なコンパイル・ステージ間の通信に一時ファイルではなくパイプを使用。コンパイルの速度は向上するが、他システムのアセンブラが対応していない場合は、指定しないほうが良い。
-Wall Warning(コンパイル時の警告)を全て表示する(推奨)
-Wp, [option, ...] optionをプリプロセッサへのオプションとして渡します。optionにカンマが含まれる場合は、 カンマの位置で分割されて複数のオプションとして渡されます。
D_FORTIFY_SOURCE=N バッファーオーバーフロー検出(O1以上の最適化オプションと併用)
  N=1の場合:コンパイル時にバッファーオーバーフロー検出
  N=2の場合:実行時にバッファーオーバーフロー検出
-fexceptions 例外処理テーブルの生成を有効にします。C++ のデフォルトです。
-fstack-protector-strong

特定の (またはすべての) ルーチンのスタック・オーバーフロー・セキュリティー・チェックを有効/無効にします。

-fstack-protector-strong を指定すると、バッファーを使用するルーチンのスタック・オーバーフロー・セキュリティー・チェックが有効になります。

--param=ssp-buffer-size=N

スタック破壊検出コードを生成するかを判定するしきい値を設定

Nにはしきい値として設定したい数値を指定。

-grecord-gcc-switches コンパイラーの起動に使用されたコマンドライン・オプションを、DWARF デバッグ情報の DW_AT_producer 属性に追加します。
-m64 インテル 64 アーキテクチャー向けにコードを生成するようコンパイラーに指示します。
-mtune

CPU 向け最適化オプション。

オプション 意味
-march 指定した CPU だけで動作するようなコードを生成します。-mcpu より速いコードを生成可能。
-mcpu -march と違い、同系列の CPU でも動作するようなコードを生成します。
-mtune GCC 3.4 系で導入された -mcpu の別名。
-D_LARGEFILE64_SOURCE "_LARGEFILE64_SOURCE"というマクロを定義状態(defined)にする。
LFS (Large File Summit) により "暫定拡張 (transitional extension)" Single UNIX Specification として規定された代替 API (alternative API) に関する定義を公開する ( 参照)。 代替 API は新規オブジェクト (関数と型) の集合で構成され、 その名前は "64" で終わる (例えば、 off_t に対応するのは off64_t、 lseek() に対応するのは lseek64() である)。 新しいプログラムではこのマクロを利用しないこと。 代わりに _FILE_OFFSET_BITS=64 を利用すること。
-DLINUX "LINUX"というマクロを定義状態(defined)にする。
C言語ではコンパイル条件をマクロで変更することがあるため。
-D_REENTRANT "_REENTRANT"というマクロを定義状態(defined)にする。
このマクロを定義すると、いくつかのリエントラント (再入可能) な関数 定義が公開される。マルチスレッドプログラムでは、この代わりに cc -pthread を使用すること。
-D_GNU_SOURCE  "_GNU_SOURCE"というマクロを定義状態(defined)にする。
C言語ではコンパイル条件をマクロで変更することがあるため。
GNU CライブラリがサポートするGNU拡張機能とOS標準を使用できるようにします。
-pthread スレッド化ユーザプロセスにlibcの代りにlibc_rをリンクします。スレッド化ユーザプロセスにリンクされるオブジェクトは-D_THREAD_SAFE付きでコンパイルする必要があります。
-c コンパイルのみ行う(オブジェクトファイルを生成する)
-o [output file] [source file...] source fileを元に、output fileを作成。source fileは複数指定可。
-Wl, [option, ...] リンカに渡すオプションを定義する。optionにカンマが含まれる場合は、 カンマの位置で分割されて複数のオプションとして渡されます。
-z [keyword] keywordとともにリンカに直接渡されます。
keyword 内容
relro オブジェクトにELF "PT_GNU_RELRO"セグメントヘッダーを作成します。
norelro オブジェクトにELF "PT_GNU_RELRO"セグメントヘッダーを作成しません。
lazy 実行可能ライブラリまたは共有ライブラリを生成するときは、それをマークして、関数が呼び出された時点(遅延バインディング)までの関数呼び出し解決を延期するように動的リンカーに指示します。
now 実行可能ライブラリまたは共有ライブラリを生成するときは、それをマークして、プログラムが起動されたとき、または共有ライブラリがリンクされているときにすべてのシンボルを解決するようにダイナミックリンカに指示します。

※動的にリンクされたELFバイナリは、GOT(Global Offset Table)と呼ばれるルックアップ・テーブルを使用して、共有ライブラリにある関数を動的に解決します。 RELRO(RELocation Read-Only)は、実行時に動的にリンクされたすべての関数を解決し、GOTを読み取り専用にするようリンカーに指示することができます。

-L [dir] コンパイラ(リンカ)がライブラリを探すディレクトリに、dirを追加する
-I [dir] コンパイラがヘッダファイルを探すディレクトリに、dirを追加する

libtoolのオプション

オプション 意味
-prefer-pic pic(position-independent code)なオブジェクトファイルを生成。
-rpath 作成されたライブラリを保存するディレクトリを指定。

 

で、結果は...動かず。なんか、mod_systemdモジュールが効いてないのか、相変わらずsystemctlがD-Busエラー。

f:id:ts0818:20180909204908p:plain

これ、解決できる気がしなくなってきますな...

しばし、模索してみます。

 

2018年9月9日(日)追記:  ↑  ここまで

 

2018年9月13日(木)追記:↓  ここから 

どうやら、Dockerなコンテナの中で、サービス起動するには、Apache httpdにmod_systemdのモジュールを入れるだけでは駄目みたいです。

www.itmedia.co.jp

techracho.bpsinc.jp

dev.classmethod.jp

⇧  上記サイト様でも仰っているように、「SysVInit/Upstart」「Monit」「Supervisor」「Systemd」なんかを導入しないと厳しそうです。

とりあえず、もう少し調査します。

2018年9月13日(木)追記:↑  ここまで 

 

注意する点としては、Dockerfile内で、ADDするときのパスの指定は、docker build でDockerfileまでのパスとして指定した場所を起点とした、相対パスにしないといけないことらしいです。

github.com

ちなみに、私の環境だと、ディレクトリとファイルの構成は、

f:id:ts0818:20180822170148p:plain

こういう状態です。

echoで複数行を改行する方法や、

qiita.com

シェルのスクリプトから、別のシェルのスクリプトを呼び出す方法は、

www.igapyon.jp

⇧  上記サイト様を参考にさせていただきました。

 

Apache Httpdソースコードからインストールした場合、httpsプロトコルを利用する場合は、SSL/TLS サーバー証明書を作成する必要があるのですが、Kubernetes、Dockerfileが組み合わさったの場合のやり方が分からず...(コンテナが作成された時点で、httpsが有効になっていて欲しい)

と思ったら、Kubernetesを使っている場合は、

qiita.com

⇧  上記サイト様によりますと、「cert-manager」というもの(Kubernetesのアドオン、拡張ライブラリみたいなものですかね?)を利用することで、SSL/TLS サーバー証明書を自動生成してくれるようです。

SSLTLSの違いについては、

ssl.sakura.ad.jp

⇧  レンタルサーバーで有名(2012年頃?からは、クラウドなどのサービスも手掛ける)な「さくらインターネット」の上記の記事が分かりやすいです。

そして、SSL/TLS通信(httpsプロトコル)ですが、

qiita.com

⇧  上記サイト様が詳しいです。

SSL/TLS通信(Httpsプロトコル)には、

のように、「公開鍵暗号方式」「共通鍵暗号方式」の2つの方法があり、名前からも分かるように、クライアント(Webブラウザなど)とサーバ(Apache Httpd、Nginx、LightSpeedなどなどのWebサーバ)のお互いに「鍵」を持たせることで通信を暗号化できるっちゅうことですかね。

公開鍵暗号方式」においては、「鍵」の正当性は、第三者である『認証局(CA:Certification Authority)』という機関から、「デジタル証明書」を取得し、「デジタル署名」に付加することで検証してるようです。

「デジタル署名」などについては、

bambinya.hateblo.jp

⇧  上記サイト様が詳しいです。 

 

で、Apache Httpdで、SSL/TLS通信(httpsプロトコル)を「公開鍵暗号方式」で実現するには、

qiita.com

⇧  上記サイト様によりますと、

サーバ側で、

  • 秘密鍵の生成
  • 公開鍵の生成
  • デジタル証明書の取得
    • 認証局に、公開鍵と各種証明書を含むCSR(certificate signing request:証明書署名要求)を送信

を行う必要があるようです。

クライアント(Webブラウザなど)では、 

通信前にクライアント側がしておくこと(は何もない)

サーバーから送られてくる証明書には、認証局秘密鍵で暗号化されたデジタル署名が含まれており、これを復号化するためには、認証局の公開鍵が必要である。主要な認証局の公開鍵は、認証局の証明書という形で、Webブラウザにプリインストールされている。

デジタル証明書とデジタル署名について - bambinya's blog

ということみたいです。

 

とりあえず、Dockerfileの記述で、ハマった点。

qiita.com

⇧  上記サイト様によりますと、CentOS 7.5では、「groupinstall」コマンドが無いみたいですね。

qiita.com

⇧  上記サイト様によりますと、オプションでイケるって言ってますね。

情報が錯綜してて、何が正解だったのかよく分からんかったけど、コンテナimageができたので、良しとしました。

 

そして、仮想マシン起動。

f:id:ts0818:20180812143923p:plain

Minikube内蔵のDockerが使えるように準備。

f:id:ts0818:20180812144156p:plain

そしたらば、Dockerfileのあるディレクトリを指定して、コンテナimageの作成。

コンテナimage名は適当な名前を自分で付けます。ローカル環境の場合は、タグを付けないと、Docker Hubのほうのコンテナimageを検索しに行ってしまうようなので、適当なタグを付けちゃいましょう。

Dockerfileっていう名前ではない、Dockerfileを作成していて、そのDockerfileを利用する場合は、

Dockerfile の指定(-f)

$ docker build -f dockerfiles/Dockerfile.debug -t myapp_debug .
$ docker build -f dockerfiles/Dockerfile.prod  -t myapp_prod .

build — Docker-docs-ja 1.11.0 ドキュメント

⇧  -f オプションで利用したいDockerfileまでのパスを指定して上げる必要があるようです。 上の例では、Dockerfile.debug、Dockerfile.prodっていう名前のDockerfileで、それぞれコンテナimageを作成しているようです。

  

docker build -t [コンテナimage名]:<タグ> [Dockerfileが配置されたディレクトリまでのパス]

ちなみに、キャッシュとか使わないで、コンテナimageを作成する方法は、

stackoverflow.com

docker build --no-cache -t [コンテナimage名]:<タグ> [Dockerfileが配置されたディレクトリまでのパス]

でいけそうです、まっさらな状態からやり直したい場合は、こっちの方法ですかね。今回は、--no-cacheオプション無しで。

f:id:ts0818:20180820231024p:plain

f:id:ts0818:20180822191718p:plain

なんやかんやで、コンテナimageはできたっぽい。(30回ぐらい失敗してるけど...エジソン先生~!)

f:id:ts0818:20180821142153p:plain

 

Kubernetesにおける、Apache Httpdhttps化に必要な証明書などの自動生成に必要なcert-managerに必要なhelmのインストールとか

github.com

⇧  「cert-manager」を利用するには、

Before deploying cert-manager, you must ensure Tiller is up and running in your cluster. Tiller is the server side component to Helm.

https://cert-manager.readthedocs.io/en/latest/getting-started/1-configuring-helm.html

「Helm」が必要ということで、

github.com

⇧  上記サイト様によりますと、Windowsの場合は、Chocolateyを利用してインストールする感じですね。 

Chocolateyのインストール方法については、

qiita.com

⇧  上記サイト様を参考。

自分は、以前にインストールしていたので、

f:id:ts0818:20180818133721p:plain

⇧  Chocolateyが入っていました。なんか、バージョンが旧くなってそうなので、

d.hatena.ne.jp

⇧  上記サイト様を参考に、

choco upgrade chocolatey

f:id:ts0818:20180818134155p:plain

⇧  どうやら、管理者権限でコマンドプロンプトを起動する必要があったよう。

f:id:ts0818:20180818134319p:plain

⇧  とりあえず、ロールバックできるらしい。

f:id:ts0818:20180818134438p:plain

⇧  ロールバックできたの?これ。とりあえず、ログを見てみます。う~ん、よく分からんかったけど、Chocolateyは、ログがどんどん蓄積されるみたい...。

とりあえず、コマンドプロンプトを管理者権限で起動して再度トライ。

f:id:ts0818:20180818135121p:plain

f:id:ts0818:20180818135222p:plain

⇧  今度はOKっぽいです。

 

そんでは、「Helm」をインストール。

f:id:ts0818:20180818135513p:plain

⇧  依存するパッケージが不足してた模様。「Y」でインストール。

f:id:ts0818:20180818135614p:plain

「Helm」がインストールできたっぽいです。

versionを確認したところ、

f:id:ts0818:20180819131812p:plain

⇧  サーバ側でエラー。仮想マシンを起動してなかった...起動。

f:id:ts0818:20180819132232p:plain

再度、helmのバージョンチェック。

f:id:ts0818:20180819132325p:plain

「tiller」がおらん、と。

これで、『Helm』の構成は、「helm」がクライアント、「tiller」がサーバ、ということが分かったわけですが、「tiller」は、 「helm」を使ってKubernetes cluster 内にインストールしてね、ってことらしいです。

INSTALLING TILLER

Tiller, the server portion of Helm, typically runs inside of your Kubernetes cluster. But for development, it can also be run locally, and configured to talk to a remote Kubernetes cluster.

helm/install.md at master · helm/helm · GitHub

⇧   Google翻訳したところ

Helmのサーバ部分であるTillerは、通常、あなたのKubernetesクラスタ内で実行されます。しかし、開発のために、ローカルで実行し、リモートKubernetesクラスタと通信するように構成することもできます。

ということらしいです。

「helm init」コマンドで、「tiller」のインストールができるようですが、オプションがいろいろあり、今回は、Kubernetesの『RBAC(Role-based Access Control)』の機能を利用できるようにしていきたいと思います。

  

Kubernetes 1.8 で RBAC(Role-based Access Control)により、アプリケーションに対するアクセス制御が標準となったようです。(Role-based Access Controlの機能自体は、Kubernetes 1.6から)

『Helm』を、RBAC環境で利用できるようにするには、Kubernetes Cluster内にサービスアカウント(たぶん、ユーザーってことですかね)を作成し、Kubernetesに存在するロールと紐づけを行う必要があるようです。

というわけで、まずは、kube-systemというNamespaceに、『tiller』という名前のサービスアカウント(ユーザー)を作成。

kubectl create serviceaccount tiller --namespace kube-system

f:id:ts0818:20180819134350p:plain

作成したサービスアカウントに、権限を付与していきます。

qiita.com

⇧  上記サイト様によりますと、「ClusterRole」が『cluster-admin』は、『クラスタの全権限をもった管理者権限。RoleBinding で namespace 内にした場合はその namespace の全権限。』ということになるそうな。

GCPGoogle Cloud Platform)の説明だと、

Kubernetes の Role または ClusterRole API オブジェクト内で権限を定義する必要があります。Role が 1 つの名前空間内のリソースへのアクセスを許可するのに対し、ClusterRole はクラスタ全体のリソースへのアクセスを許可します。

役割ベースのアクセス制御  |  Kubernetes Engine  |  Google Cloud

⇧  「Role」「ClusterRole」の2種類が存在するみたい。今回は、「ClusterRole」を利用していく感じで。

それでは、作成したサービスアカウント『tiller』に「ClusterRole」をバインディングすることで、「ClusterRole」の持つ権限を『tiller』に付与します。 

kubectl create clusterrolebinding tiller --clusterrole=cluster-admin --serviceaccount=kube-system:tiller    

f:id:ts0818:20180819140604p:plain

「helm」を使って、サービスアカウント(ユーザー)『tiller』で、「Tiller」をKubernetes cluster 内にインストールします。 

helm init --upgrade --service-account tiller    

f:id:ts0818:20180819141111p:plain

⇧  「Tiller」がインストールできたようです。「chars」と呼ばれる、パッケージのリポジトリも『Adding stable repo』とあるので、利用できるようになったちゅうことですかね。

 

versionの確認したところ、ファイアーウォールの警告が出た場合などは、「アクセスを許可する(A)」で。(プライベートネットワークにしたほうが良かったのかな?)

f:id:ts0818:20180819141345p:plain

今度は、サーバ側も問題なしということで。

f:id:ts0818:20180819141543p:plain

 

 ちょいと脱線して、「Helm」「Tiller」「Kubernetes」の関係性ですが、

Both the Helm client and Tiller are written in Go and uses gRPC to interact with each other. Tiller (as the server part running inside Kubernetes) provides a gRPC server to connect with the client and it uses the k8s client library to communicate with Kubernetes. It does not require it’s own database as the information is stored within Kubernetes as ConfigMaps.

Manage Helm repositories and deploy charts via REST · Banzai Cloud

⇧  上記サイト様の図が分かりやすいので参考にさせていただき、イメージ図を作成。 

 

f:id:ts0818:20180824224624p:plain

 ⇧  ローカル環境だと、こんなイメージですかね?

Kubernetesクラスタを操作する際には、CLIツールのkubectlとYAML形式で書かれたManifestファイルを用いてKubernetes Masterに「リソース」の登録を行います。実際にはkubectlも内部でKubernetes MasterのAPIを叩いているだけなので、ライブラリやcurlなどでも操作することが可能です。

Kubernetesの基礎 | Think IT(シンクイット)

⇧  上記サイト様を参考に、kubectlで実行される処理に関しては、kube-apiserver を経由して、etcd に「リソース」が登録されると推測。 

Dockerはkubelet->CRI->Docker->containerd->OCI->runC->コンテナイメージを起動、という流れだが、cri-oの場合は、kubelet->CRI->cri-o->OCI->runC->コンテナイメージ、containerdに至ってはkubelet->CRI->cri-containerd->gRPC->containerd->OCI->runC->コンテナイメージという流れになる。しかしKubernetes 1.10、containerd 1.1以降はkubelet->CRI->containerd->OCI->runC->コンテナイメージという流れに変わっているという。

runC vs. cc-runtime vs. kata-runtime?コンテナランタイムの内部構造と性能比較 | Think IT(シンクイット)

⇧  上記サイト様を参考に、 今回は、Kubernetes 1.10 を利用しているので、上図のようなイメージ図になりました。(Kubernetesに関しても素人なので、あくまで参考程度に捉えてもらえれば)

まぁ、何ていうか、公式のサイトにこういうアーキテクト図を掲載してくれたら全体像がイメージしやすいんですが...

探し方が下手くそ過ぎて見つけられないだけかもしれませんが。(情報が見つからなさ過ぎ、且つ、公式の説明が初心者にとって端折られ過ぎてて疲れる...内輪で盛り上がるんじゃくて、もっとみんなで共有っていう気持ちがまったく感じられない気が酢豚が食べたい...そんな哀しい気分になりますね)

 

cert-managerをインストール

ソースコードからインストールということで、curlコマンドが必要です。

インストールがお済み出ない場合は、

web.plus-idea.net

qiita.com

⇧  上記サイト様が参考になるかと。OS XMac)の場合は、使ったことが無いので分かりませんが、OS XMac)は、BSDBerkeley Software Distribution)というUNIXのOSがベースになってるらしいので、Windowsほど手間ではないかと。(curlは、Unix系のコマンドとして利用されてきたようなので)

 

で、自分の場合は、前にインストールしていたのですが、

f:id:ts0818:20180819143622p:plain

⇧  バージョンが旧そう...

コマンドプロンプトを管理者権限で起動して、chocolateyで検索。

f:id:ts0818:20180819144443p:plain

⇧  chocolateyでインストールできるcurlの最新は、curl 7.61.0 らしい。

アップデートしちゃいます。 

f:id:ts0818:20180819144729p:plain

f:id:ts0818:20180819144841p:plain

⇧  アップデートできたっぽい。

f:id:ts0818:20180819144906p:plain

そんでは、https://github.com/jetstack/cert-manager/releases

github.com

にアクセスして、Windowsだと、「Source code(zip)」かな?と思ったけど、

ascii.jp

⇧  Windows 10のある時期からは、tarコマンドも使えるようになってるらしい。

f:id:ts0818:20180819150326p:plain

⇧  確かに、インストールした覚えがないけど、何かインストールされてるっぽい。

でもWindows 7 だと、

oshiete.goo.ne.jp

⇧  上記サイト様で仰っているように、Windowsに疑似的なUnix環境を構築するか、7zipのコマンドをインストールしていれば、tarの展開(解凍)もいけるそう。

ちなみに、7zipのコマンドは、chocolateyでインストールできるっぽいですね。

f:id:ts0818:20180819151006p:plain

脱線してしまいましたが、せっかくtarコマンドが使えるって言ってるので、今回は、「Source code(tar.gz)」のリンク上で右クリックして「リンクのアドレスをコピー(E)」。

f:id:ts0818:20180819151237p:plain

そしたらば、curlコマンドでダウンロード、展開(解凍)。

qiita.com

⇧  上記サイト様によりますと、Unix系のtarコマンドとWindows版のtarコマンドは扱いが異なりそうです。

Windows版のcurl(version 7.61.0)だと、展開(解凍)には、zオプションは必須みたいな感じですかね?

curl -sL https://github.com/jetstack/cert-manager/archive/v0.4.1.tar.gz | tar zxv

f:id:ts0818:20180819152826p:plain

ダウンロードと展開(解凍)まではできたようです。

f:id:ts0818:20180819153156p:plain

そんでは、cert-managerのインストール。

helm install --name cert-manager --namespace kube-system cert-manager-0.4.1/contrib/charts/cert-manager

f:id:ts0818:20180819153354p:plain

f:id:ts0818:20180819153742p:plain

⇧  インストールできたようです。

 

cert-managerは、Kubernetesのアドオン

プロジェクトに説明があるんですが、

github.com

cert-manager is a Kubernetes add-on to automate the management and issuance of TLS certificates from various issuing sources.

It will ensure certificates are valid and up to date periodically, and attempt to renew certificates at an appropriate time before expiry.

GitHub - jetstack/cert-manager: Automatically provision and manage TLS certificates in Kubernetes

⇧  上記サイト様の図を見る限り、Kubernetes側で、「Config&Storageリソース」である「Secret」を用意する必要がありそうですかね?

それぞれの役割は、こんな感じらしい。(ただし、kube-logoとかkube-cert-managerの概要図を拝借してるみたいなんで、あんま参考にならなさそうね...自分たちのプロジェクトなのに、そのへん雑過ぎでしょ...)

f:id:ts0818:20180819165855p:plain

 

ACME(Automatic Certificate Management Environment )って?

なんか、cert-managerのチュートリアルやろうとして、

This section contains tutorials that specifically utilise the ACME Issuer. They are designed to help teach the underlying concepts of cert-manager whilst also helping ‘quickstart’ common use-cases for the project.

ACME Issuer Tutorials — cert-manager documentation

⇧  いきなり、「ACME」とか言われてもね...

Wikipedia先生!

Automated Certificate Management Environment (ACME) プロトコルは、認証局間の相互作用を自動化するための通信プロトコル で、利用者のWebサーバにおいて非常に低コストで公開鍵基盤の自動展開が可能である。Let's Encryptサービスに対して、Internet Security Research Group英語版によって設計された。

ACME プロトコルは、HTTPS上でJSON形式のメッセージ渡しに基づくプロトコルで、インターネットドラフトとして公開されている。

Internet Security Research Groupは、ACMEオープンソースソフトウェアリファレンス実装を提供:lets-encrypt-previewは、PythonによるACMEプロトコルを使用したサーバ証明書管理ソフトウェアの試験的実装であり、boulder は、Go言語で書かれた認証局の実装である。

Automated Certificate Management Environment - Wikipedia

う~ん、Let's Encrypt 以外は対応してないって考えて良いのかしら?

ssl.sakura.ad.jp

⇧  サーバ証明書については、上記サイト様が詳しいです。

 

cert-managerをクラウドを使わずにローカルでやりたかったんだけど...

ACMEサーバ証明書を取得できるらしいんですが、 

cert-manager can be used to obtain certificates from a CA using the ACME protocol. The ACME protocol supports various challenge mechanisms which are used to prove ownership of a domain so that a valid certificate can be issued for that domain.

Issuing an ACME certificate using HTTP validation — cert-manager documentation

⇧  公式のサイトの説明だと、

cert-managerを使用すると、ACMEプロトコルを使用してCAから証明書を取得できます。 ACMEプロトコルは、ドメインの所有権を証明するために使用される様々なチャレンジメカニズムをサポートしているため、そのドメインに対して有効な証明書を発行することができます。』 

となっていて、cert-manager で利用できるチャレンジは、

  • DNS-01
  • HTTP-01

の2つ のようです。

で、利用できるIssureのタイプが、

cert-manager has been designed to support pluggable Issuer backends. The currently supported Issuer types are:

Issuing an ACME certificate using HTTP validation — cert-manager documentation

Name Description
ACME Supports obtaining certificates from an ACME server, validating with HTTP01 or DNS01
CA Supports issuing certificates using a simple signing keypair, stored in a Secret in the Kubernetes API server
Vault Supports issuing certificates using HashiCorp Vault.
Self signed Supports issuing self signed certificates

さっそく、アーキテクト図のIssures とかみ合ってないし...っていうか、IssuresってIssureと関係ないの?

 

さらに、ingress-shimってのも必要らしい、で、Ingress Controllerがnginxのものしか無いらしい

なんか、

cert-manager can be configured to automatically provision TLS certificates for Ingress resources via annotations on your Ingresses.

A small sub-component of cert-manager, ingress-shim, is responsible for this.

ingress-shim — cert-manager documentation

⇧  公式のサイトの説明だと、

cert-managerは、Ingressリソースである、Ingressアノテーションを使用して、TLS証明書を自動的にプロビジョニングするように設定できます。これを実現するのが、cert-managerのコンポーネントである、ingress-shimです。

何じゃ、そりゃ...。  

Since cert-manager v0.2.2, ingress-shim is deployed automatically as part of a Helm chart installation.

ingress-shim — cert-manager documentation

⇧  cert-manager-0.2.2 からは、 よく分からんけど、ingress-shimは自動で有効になってるみたい?確かに、「helm」で「tiller」をインストールした際に、chartsっていうリポジトリが追加されてたから問題なくingress-shimは使えるようになってるってことですかね。

そして、Ingressリソースを監視する、Ingress Controllerっちゅうのが必要らしく、

github.com

⇧  いまのところ、Ingress Contollerについては、

 があるようです。

 Nginxは、未だによく分からんのだけど...選択肢がないから使わねばならぬですね。

 

shimって?

なんか、dockerのコンテナruntimeをキック(起動)する際の、kubeletに内包されていたdockershimといい、ingress-shimといい、shimって何じゃ?

Not to be confused with shm, an abbreviation for shared memory, often pronounced "shim".

In computer programming, a shim is a small library that transparently intercepts API calls and changes the arguments passed, handles the operation itself or redirects the operation elsewhere.Shims can be used to support an old API in a newer environment, or a new API in an older environment. Shims can also be used for running programs on different software platforms than they were developed for.

Shims for older APIs typically come about when the behavior of an API changes, thereby causing compatibility issues for older applications which still rely on the older functionality; in such cases, the older API can still be supported by a thin compatibility layer on top of the newer code. Shims for newer APIs are defined as: "a shim is a library that brings a new API to an older environment, using only the means of that environment."

Shim (computing) - Wikipedia

shimは、API呼び出しを透過的にインターセプトし、渡された引数を変更したり、操作自体を処理したり、操作を別の場所にリダイレクトする小さなライブラリです。』 

ってことみたいっすね...そういう設計ってことですかね。

 

cert-managerの流れを整理

ちょっと、cert-managerの動きを整理してみます。

まずは、Ingressリソースを監視するという、Ingress Controllerですが、

What is an Ingress Controller?

Configuring a webserver or loadbalancer is harder than it should be. Most webserver configuration files are very similar. There are some applications that have weird little quirks that tend to throw a wrench in things, but for the most part you can apply the same logic to them and achieve a desired result.

The Ingress resource embodies this idea, and an Ingress controller is meant to handle all the quirks associated with a specific "class" of Ingress.

An Ingress Controller is a daemon, deployed as a Kubernetes Pod, that watches the apiserver's /ingresses endpoint for updates to the Ingress resource. Its job is to satisfy requests for Ingresses.

GitHub - kubernetes/ingress-nginx: NGINX Ingress Controller for Kubernetes https://kubernetes.github.io/ingress-nginx/

Ingress Controllerは、Kubernetes Podとしてデプロイされるデーモンで、Apiserver / IngressエンドポイントがIngressリソースの更新を監視します。』 

う、う~ん...。

 

https://adtech.cyberagent.io/techblog/archives/3758

⇧  上記サイト様によりますと、クラウドの、GCPGoogle Cloud Platform)のコンテナ環境である、GKE(Google Container Engine)などでは、手軽に構築できると。

どうやら、いまのとこ選択肢としては、

  1. GKE(Google Container Engine) の Ingress
  2. Nginx Ingress Controller
  3. nghttpx-ingress-controller
  4. 自作

みたいな感じで、ローカル環境だと、2~4のどれかを利用していく感じになるようです。クラウド環境は、GCPGoogle Cloud Platform)以外にもAWSのalb-ingress-controller 等でIngress Controllerを実施できるようです。

 

イメージ図にしてみると、

f:id:ts0818:20180824224951p:plain

⇧  黄色く塗ったとこが、cert-managerを利用する際に必要、もしくは用意しておかないといけないものになる感じですかね? 

図が分かりにくいですが、Service(L4 LoadBalancer)== Nginx Ingress Controllerという想定です。

「helm」でcert-managerをインストールすると、Pod(cert-manager)ができるらしく、そこからは、Issures、Certificates、Nginx Ingress Controllerなどを作成していく感じですかね 。

Ingress Controllerについては、

developers.freee.co.jp

⇧  上記サイト様が詳しいです。

 

 

cert-managerでサーバ証明書を自動生成してみる

今回は、HTTP-01 でトライということで。まずは、Ingress Controllerを準備する必要があります。Nginx Ingress Controllerを利用するということで、

Since cert-manager v0.2.2, ingress-shim is deployed automatically as part of a Helm chart installation.

ingress-shim — cert-manager documentation

⇧  上記サイト様によりますと、「helm」でインストールが良さげらしいです。

github.com

 

さっそく、「helm」でNginx Ingress Controllerをインストール。

www.yuuniworks.com

⇧  上記サイト様のインストールの仕方の方が良いと思われます。

⇩  自分は、上記サイト様を見つける前にインストールしてしまったので、下記コマンドで実施してしまいましたが....

helm install stable/nginx-ingress --name my-nginx

f:id:ts0818:20180820165651p:plain 

f:id:ts0818:20180820165740p:plain

⇧  とりあえず、Nginx Ingress Controllerがインストールされたらしい。 

で、Nginx Ingress Controllerに固定IPを指定したほうが良いらしいので、サービスを確認し、

f:id:ts0818:20180822154301p:plain

kubectl edit svc [Ingress Controllerのサービス名]

f:id:ts0818:20180822152847p:plain

ファイルが開けるので、「type: LoadBalancer」って行の下に、

f:id:ts0818:20180822153204p:plain

「loadBalancerIP:xxxxxxx」みたいな感じで設定し、保存し閉じます。

f:id:ts0818:20180822153447p:plain

 

 

続いて、Issuresを用意。練習環境ということで「letsencrypt-staging」のIssuresで。

で、マニフェストファイル(YAML、またはJSON形式)を用意する必要があるらしいんだけど、どこに配置すれば?

Windowsのことなら、Microsoftさん!

docs.microsoft.com

どうやら、どのディレクトリに作っても良いみたい、ただし、実行するときに作成したマニフェストファイルのパスを指定。

というわけで、適当な場所にマニフェストファイルを作成。ファイルの名前も好きに付けて良いみたいです。

「C:¥Users¥Toshinobu¥.minikube¥machines¥minikube¥minikube¥manifest」というディレクトリに配置しました。

f:id:ts0818:20180820172050p:plain

 

apiVersion: certmanager.k8s.io/v1alpha1
kind: Issuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: user@example.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    http01: {}

emailの部分は、ご自分のメールアドレスに置き換えていただく感じで。

そんじゃ、マニフェストファイルからIssuresを生成。

kubectl apply -f <Path to Manifest file>

f:id:ts0818:20180820173332p:plain

⇧  Issuresが作成されたらしい。

 

applyコマンドについては、

speakerdeck.com

⇧  上記スライドが分かりやすいです。

 

続きまして、Certificatesに必要となる、Ingressを作成していきます。ネット上だと、「Issures」「Certificates」「Ingress」の順番で作成してる人が多いんだけど、

If the ingress field is specified, then an Ingress resource with the same name in the same namespace as the Certificate must already exist and it will be modified only to add the appropriate rules to solve the challenge. This field is useful for the GCLB ingress controller, as well as a number of others, that assign a single public IP address for each ingress resource. Without manual intervention, creating a new ingress resource would cause any challenges to fail.

Issuing an ACME certificate using HTTP validation — cert-manager documentation

If the ingressClass field is specified, a new ingress resource with a randomly generated name will be created in order to solve the challenge. This new resource will have an annotation with key kubernetes.io/ingress.class and value set to the value of the ingressClass field. This works for the likes of the NGINX ingress controller.

Issuing an ACME certificate using HTTP validation — cert-manager documentation

If both are specified, then the ingress field will take precedence.

Issuing an ACME certificate using HTTP validation — cert-manager documentation

⇧  公式のHTTP01のチュートリアルの説明だと『ingress』『ingressClass』の両方が、Certificatesのためのマニフェストファイルに設定されてる場合、Ingress リソースが既に作成されていないといけないらしい。

 

www.yuuniworks.com

⇧  上記サイト様のように、もしかしたら、 「Ingress」「Issures」「Certificates」の順番で作成するのが正解かもしれないですね。

  

そして、ingress を作成するに当たって、PodをService付きで作成しておかないとマズイようです。要するに、コンテナ化アプリケーションのデプロイをしておかないといけないようです。

httpsの自動化ってことで、cert-managerでサーバ証明書を取得してからコンテナ化アプリケーションをデプロイするんだと思っていましたが、HTTP01の場合は、事前にhttpの状態でコンテナ化アプリケーションを起ち上げとかないと駄目みたいですね。

 

qiita.com

⇧  上記サイト様によりますと、DNS01のチャレンジだと、 最後にデプロイするのでも問題ないみたいですね。

まぁ、今回はHTTP01のチャレンジということで、コンテナ化アプリケーションをデプロイしておきます。今回は、

reiki4040.hatenablog.com

⇧  上記サイト様を参考に、自分でYAMLを用意してデプロイしてみます。

まずは、Deployment(Replicaset、Podも自動生成される)のためのYAMLを作成したかったのですが、残念ながら、Deploymentは、restartPolicyというものが設定できないらしい。

stackoverflow.com

⇧  どうも、dockerの残念な仕様のせいで、restartPolicyを設定しておかないと、マズイらしい。

stackoverflow.com

⇧  restartPolicyだけでも駄目で、DockerfileのCMDか、Podのマニフェストファイルで、コンテナが起動し続けるように、無限ループっぽい処理を追加する必要があるらしい...このステキ過ぎるDockerコンテナの仕様って...もはやバグですやん。

Kubernetesの公式サイトにも載ってなかったりで、おかげさまで、2日ぐらい調査で丸々潰れました(涙)。

もしかしたら、無限ループさせれば、restartPolicyは必要ないかも(restartPolicyを明示的に設定しない場合、デフォルトでrestartPolicy:Alwaysが設定されてるらしい。)

いまのとこ、restartPolicyが設定できるのは、「job」「pod」のどちらかでしか指定できないらしい。「job」と「pod」の違いについては、

thinkit.co.jp

⇧  上記サイト様が詳しいです。

ということで、今回は、「pod」で。

f:id:ts0818:20180823134842p:plain

利用するコンテナimageを確認し、

f:id:ts0818:20180822160257p:plain

apiVersion: v1
kind: Pod
metadata:
  name: httpd-tom-java
spec:
  containers:
  - name: httpd-tom-java
    image: cent_java_tom_httpd:10
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "while true; do sleep 30; done;" ]
    ports:
    - containerPort: 80
  restartPolicy: OnFailure

f:id:ts0818:20180823153817p:plain

 続きまして、ServiceのためのYAMLとして、『service.yml』 を作成。

f:id:ts0818:20180822171625p:plain

apiVersion: v1
kind: Service
metadata:
  name: httpd-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: httpd-tom-java

f:id:ts0818:20180822193940p:plain

 

 そして、Ingressを作成。serviceNameには、上記で作成したServiceのmetadataのnameの名前を設定。

『issures.yml』と同じディレクトリに『ingress.yml』を配置。

f:id:ts0818:20180821162109p:plain

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    # nginx-ingressを、Ingress Contollerとして使用する
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt-staging
    certmanager.k8s.io/acme-challenge-type: http01
    kubernetes.io/tls-acme: "true"
spec:
  rules:
  - host: www.example.com
    http:
      paths:
      - backend:
          serviceName: httpd-nodeport
          servicePort: 80
  tls:
  - secretName: example-com-tls
    hosts:
    - www.example.com

f:id:ts0818:20180821162727p:plain

 

 作成したIssures、Ingressの情報を基に、Certificatesを作成するので、新たにマニフェストファイルを用意。

f:id:ts0818:20180821162802p:plain

apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: example-com
  namespace: default
spec:
  secretName: example-com-tls
  issuerRef:
    name: letsencrypt-staging
  commonName: example.com
  dnsNames:
  - www.example.com
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - example.com
    - http01:
        ingress: my-ingress
      domains:
      - www.example.com

ingress」には、Ingress Controllerの名前を指定。「ingressClass」は「nginx」で大丈夫かと。他はご自分の環境に合わせていただく感じで。私は、チュートリアルのものをそのまま利用しました。

f:id:ts0818:20180820174643p:plain

⇧  実行されました。

kubectl describeコマンドで、証明書が作成されたか確認できるらしい。 

kubectl describe certificate

f:id:ts0818:20180820231823p:plain

f:id:ts0818:20180821163230p:plain

⇧  はい、エラー...何だかなぁ~。おそらく、ドメインIPアドレスの紐づけあたりの問題なんでしょうね。DNSによる名前解決ができないみたいな。

 

qiita.com

いつまでたっても EXTERNAL-IP が <pending> のままでロードバランサーが作られることはありません。というのも Kubernetes の中でロードバランサーを作成し、Service の EXTERNAL-IP をロードバランサーの IP アドレスに設定する、という処理を担当する controller が動いていないからです。(いないから。

Kubernetes の Service type LoadBalancer を手作業で作る

 ⇧  上記サイト様によりますと、ローカル環境だと、 EXTERNAL-IPを設定してくる役割のものがいないんだとか。どうりで、上手くいかないわけですね。

Kubernetes does not offer an implementation of network load-balancers (Services of type LoadBalancer) for bare metal clusters. The implementations of Network LB that Kubernetes does ship with are all glue code that calls out to various IaaS platforms (GCP, AWS, Azure…). If you’re not running on a supported IaaS platform (GCP, AWS, Azure…), LoadBalancers will remain in the “pending” state indefinitely when created.

MetalLB, bare metal load-balancer for Kubernetes

⇧  ベアメタル環境、要するにクラウド環境でない場合は、LoadBalancerで EXTERNAL-IPは永久に保留状態のままっちゅう...こういう説明を端折るなっちゅう話ですよ、公式のチュートリアルで。

 

github.com

⇧  上記サイト様で、「Internet -> (1) HAProxy :443 -> (2) Nginx-Controller SSL/Term -> (3) Nginx :8080 -> Wordpress :php-fpm」って流れを実現したって言ってるので、HAProxyを導入していくしか無さそうですかね。

  

HAProxyってコンテナを起ち上げる必要があるっぽいので、HAProxy用のコンテナimageを作成ですかね。

Docker 1.5が出た.IPv6のサポートやstatsコマンドによるコンテナのメトリクス表示などが追加された.ユーザ的に一番嬉しいのはDockerfileの名前を自由に決められるようになったことだろうと思う.

Docker 1.5の変更点 | SOTA

⇧  上記サイト様によりますと、Dockerfileっていう名前じゃなくてもイケるのね、どうりでネット上で、Dockerfileじゃない名前のファイルでコンテナimageを作成してる人を見かけたわけですね。

というわけで、「HAProxyfile」っていうDockerfileの作成と、

f:id:ts0818:20180823175118p:plain

「C:¥Users¥Toshinobu¥.minikube¥machines¥minikube¥minikube¥haproxy_conf」というディレクトリを作成し、「haproxy.cfg」を配置しました

f:id:ts0818:20180823182153p:plain

HAProxyfile

FROM centos:7.5.1804

# update, install required, clean
RUN yum -y update && yum install -y haproxy && yum clean all 

# setup haproxy configuration
ADD ./haproxy_conf/haproxy.cfg /etc/haproxy.conf

# Expose ports
EXPOSE 80
EXPOSE 443
EXPOSE 1936

CMD ["haproxy", "-f", "/etc/haproxy.conf"]

 

github.com

⇧  HAProxyの設定は、上記サイト様を参考。

haproxy.cfg

global
    maxconn 256

defaults
    mode http
    timeout client     120000ms
    timeout server     120000ms
    timeout connect      6000ms

listen http-in
    bind *:80
    server server1 192.168.99.100:31742

listen https-in
    bind *:443
    server server1 192.168.99.100:32170

「haproxy.cfg」で設定してるIPアドレスはminikube ipコマンドで表示されたものを、ポートは、kubectl get svcコマンドで表示されるnginx-ingress-controller(Type:LoadBalancer)のものを設定してます。

で、

github.com

⇧  上記サイト様によりますと、Nginx Ingress ControllerのConfigMapのYAMLを編集して、「use-proxy-protocol:"true"」という設定を追加するらしい。

 

下記コマンドでminikubeのダッシュボードに遷移して、

minikube dashboard

f:id:ts0818:20180823203448p:plain

⇧  Ingress ControllerっぽいConfigMapが2つあるんだが... 

まぁ、ラベルがいっぱい付いてるほうを編集するということで、f:id:ts0818:20180823203816p:plainをクリックし

f:id:ts0818:20180823203754p:plain

⇧  「YAMLを見る/編集する」を選択。

f:id:ts0818:20180823204003p:plain

 ⇧  ってなってるので、"data"の部分に、「use-proxy-protocol:"true"」を追記。

f:id:ts0818:20180823204219p:plain

⇧  そしたらば、「アップデート」で。

  

では、コンテナimageの作成。

f:id:ts0818:20180823191319p:plain

f:id:ts0818:20180823191711p:plain

そしたらば、HAProxyのコンテナを作成。 

docker run -d --name [コンテナ名] -p [ホストのポート]:[コンテナのポート] [コンテナimage]

f:id:ts0818:20180823223557p:plain

で、Serviceで、TypeがLoadBalancerのもの、つまり、Nginx Ingress Controllerは相変わらずExternal IPが設定されず、万年待機中な感じですかね。

 

翌日。HAProxyは断念。ちなみに仮想マシンを停止すると、Dockerで作成したコンテナは停止するようなので、HAProxyは機能しなくなっているかと。

qiita.com

⇧  上記サイト様によりますと、ローカル環境の場合は、「MetalLB」を使う方が良さ気ですかね。

というわけで、「MetalLB」を導入。

  • BGP(Border Gateway Protocol)
  • Layer2(L2スイッチ)

の2つのモードがあるそうですが、

qiita.com

⇧  上記サイト様によりますと、「Layer2」モードでNginx Ingress Controllerと連携されてるようなので、「Layer2」モードでトライしていきたいと思ったら、

The Layer 2 tutorial demonstrates setting up layer 2 mode. For this tutorial you will need to bring your own bare metal cluster, unfortunately we don’t yet have a Minikube-friendly demonstration for layer 2 mode.

MetalLB, bare metal load-balancer for Kubernetes

⇧ Minikubeの場合、Layer2モードは、いまのところ無理っぽい。 仕方がないので、「BGP(Border Gateway Protocol)」で行くしか無さ気。

 

「MetalLB」のリリースは、

github.com

⇧  上記サイト様で把握できるようです。

 

チュートリアルによると、用意されてるYAMLファイルをインストールすればOKのようです。

「BGP(Border Gateway Protocol)」の場合は、

MetalLB exposes load-balanced services using the BGP routing protocol, so we need a BGP router to talk to. 

MetalLB, bare metal load-balancer for Kubernetes

⇧  BGP router を用意する必要があるようです。

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/test-bgp-router.yaml

f:id:ts0818:20180824145708p:plain

 

続いて、MetalLB をインストール。 

This manifest creates a bunch of resources. Most of them are related to access control, so that MetalLB can read and write the Kubernetes objects it needs to do its job.

MetalLB, bare metal load-balancer for Kubernetes

なので、チュートリアルにある、 

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml

f:id:ts0818:20180824142607p:plain

を実行すると、

f:id:ts0818:20180824142753p:plain

⇧  metallb-systemというNamespaceにpodが2つできます。

 

続いて、MetalLBのConfigMapを作成。

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/tutorial-3.yaml

f:id:ts0818:20180824152136p:plain

そしたらば、Nginx Ingress ControllerのServiceのYAMLを編集します。まずは、Serviceの確認。 

f:id:ts0818:20180824153240p:plain

では、Nginx Ingress ControllerのYAMLを編集。

f:id:ts0818:20180824153914p:plain

loadBalanceIPを、

f:id:ts0818:20180824153450p:plain

「manifests/tutorial-3.yaml」で設定されている「address: 198.51.100.0/24」の範囲のものに合わせます。

f:id:ts0818:20180824153537p:plain

画像が小さくて申し訳ないですが、External IPが設定されました。 

f:id:ts0818:20180824154038p:plain

「MetalLB」のリロードをするらしい。

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/tutorial-4.yaml

f:id:ts0818:20180824202551p:plain

で、curlでExternal IPに接続できるらしいんですが、

f:id:ts0818:20180824162312p:plain

f:id:ts0818:20180824160332p:plain

f:id:ts0818:20180824162035p:plain

繋がらず...

 

ちょっと、調査します。

2週間ぐらいやって、解決できなかったんで、答えにたどり着くまでに相当に時間がかかりそうな...もしくは解決できずにお蔵入りかも...その時は申し訳ないです。

哀しいほど、盛大に時間を無駄にしてしまった...。

ローカル環境のcert-managerの構築で、誰か良き方法を知ってる方がいらしたら教えていただけるとありがたいです。

 

2018年8月27日(月)追記:↓  ここから

なんか気になったのは、MetalLBのほうで、

https://metallb.universe.tf/tutorial/minikube/ の見本だと、「Neighber address: 192.168.99.100」ってMinikubeのIPになってるんだけど、

f:id:ts0818:20180827233442p:plain

わたくしのは、「Neighber address: 10.0.2.15」になっとるのですが...

f:id:ts0818:20180827233407p:plain

自分のMinikubeの仮想マシンのネットワークでNATの設定が、「10.0.2.15」になってるぽいんだが、原因これっすかね?

もうちょっと調査してみます。

2018年8月27日(月)追記:↑  ここまで

 

2018年9月1日(土)追記:↓  ここから

なんか、ログを見た限りでは、BGP RouterとMinikubeの接続は確立されているらしい。 

ts0818.hatenablog.com

引き続き、調査してみます。

 

2018年9月1日(土)追記:↑  ここまで

2018年9月1日(土)追追記:↓  ここから 

どうやら、コンテナでhttpdサーバが起動していなかったようです、コンテナimageを作成し直して、httpdが起動するように修正中です。まだ完成していませんが、それで解決してくれれば良いのですが...

f:id:ts0818:20180902000913p:plain

⇧  現状、コンテナ内で確認したところ、httpdの起動プロセスが無いっす...

 

2018年9月1日(土)追追記:↑ ここまで

 

 

 

今回は、このへんで。