Laravel環境の設定を切り離そう
Contents
Caution
未チェックの項目のあるドラフト版です
Laravel環境の設定を切り離そう#
先ほど作ったLaravel環境のマニフェストは、このままだとセキュアな情報を内包したままで出しております。 この部分をできるだけ隠すことができないでしょうか。
secretの利用でDBの情報を隠す#
まず、データベース部分のマニフェストを見てみましょう。
limits:
memory: "128Mi"
cpu: "500m"
# 現時点では環境変数渡し
env:
- name: MARIADB_RANDOM_ROOT_PASSWORD
value: "1"
- name: MARIADB_DATABASE
value: sample
- name: MARIADB_USER
value: memoadmin
- name: MARIADB_PASSWORD
value: admin
volumeMounts:
- mountPath: /var/lib/mysql
name: db-store
この部分は、DB名やアカウント情報は秘匿しておいた方が良いでしょう。 対応するsecretを作成してみましょうか。
secretリソースの作成#
ということで早速作ってみます。
apiVersion: v1
kind: Secret
metadata:
name: db
type: Opaque
data:
# 例示用に各値の元のものを出していますが
# 本来はやめましょうね
# sample
dbname: c2FtcGxl
# memoadmin
user: bWVtb2FkbWlu
# admin
password: YWRtaW4=
各変数の値はBase64エンコードで保持しておくことを忘れないでください(マニフェストが通らなくなります)。
マウントしての利用#
これらに対応するように、参照側をざっと書き改めてみます。 環境変数に値がでないように、ファイルに出す形式にしてみましょう。
# バックエンド(mariadb)
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: mariadb:10.9.4
resources:
limits:
memory: "128Mi"
cpu: "500m"
# 現時点では環境変数渡し
env:
- name: MARIADB_RANDOM_ROOT_PASSWORD
value: "1"
- name: MARIADB_DATABASE_FILE
value: /config/dbname
- name: MARIADB_USER_FILE
value: /config/user
- name: MARIADB_PASSWORD_FILE
value: /config/password
volumeMounts:
- mountPath: /var/lib/mysql
name: db-store
- mountPath: /config
name: db-secret
ports:
- containerPort: 3306
readinessProbe:
exec:
command:
- mysqladmin
- ping
- "-u"
- memoadmin
- "--password=admin"
- "-h"
- "127.0.0.1"
volumes:
- name: db-store
persistentVolumeClaim:
claimName: db-store
- name: db-secret
secret:
secretName: db
ポイントは3カ所ありました。
secretもボリュームとして設定でき、キー名のファイルが作られます
ボリュームとして宣言したものを適当な場所にマウントさせます
(mariadb)各環境変数名に
_FILE
を付与し、参照ファイルを指定します
これにより、パスワードなどの情報を秘匿した状態で利用可能となります。
.envファイルの問題#
Laravelでは、データベース接続の設定は、プロジェクトディレクトリ上にある .env
ファイルによって処理されます。
しかし、githubなど公開されうる場所でパスワード情報の入っているようなファイルを置くべきではありません。
この問題にどう対応するかはいろいろ考えられます。
パスワード以外の情報による
.env
を再構成し、秘匿情報はsecretを用いて環境変数で渡す.env
をconfigMapもしくはsecretで渡す
前者はMariaDB側で対応しているのに…感はあるのですが、実はsecret自体は存在しているので、secretKeyRef
を用いることで同じ値を使い回せます(変更忘れを防げる)。
変数が見えても良いのであれば選択肢としては考慮にたると思います(この場合はもちろんmariadb側も_FILE
使わないとなることでしょう)。
そこで今回は、後者からsecretで渡すことを考えてみたいと思います。
secretから渡す方法も、雑に2つ考えられます。
.env
ファイルをsecretから作られた疑似ファイルに対してシンボリックリンクを貼って対応する.env
ファイルをsecretから作られた疑似ファイルをinitContainers内でコピーして対応する
後者はイメージを書き換えずに対応できるかと思うのですが、initContainersとcontainersによるコンテナが同じディレクトリを共有状態にしていないと効果を持たないため難しいと思われます(チャレンジしがいはありそうですが)。
今回は前者の方式でイメージを書き換えてから使ってみましょう。
forkして準備する#
各自で作業してもらいたいので、まずは元ソースをforkしていきましょう。
そしてforkを呼び出します。

Fig. 28 フォークの呼び出し#
フォーク後の名前は適当に選べますが、ここでは変えずにそのまま使うことにします(重複してなければOK)。

Fig. 29 forkした後の名前設定#
これで実行させれば、自分のリポジトリにforkを生成できるので、こちらから取得して書き換えていきます。
ということで、git clone
をしてから次に進みましょう。
PS> git clone https://github.com/USERNAME/laravel-sample-remastered.git
ファイルのコピーと削除#
.env
は、クローンしたディレクトリのlaravel/sample
にあります。LinuxやmacOS環境ではドットファイルのため隠れて見えません。
Tip
もちろん ls -a
で確認できますよ。
ここでは、dotenv
という名前で作ることにします。
PS> kubectl create secret generic dotenv --from-file ./.env
secret/dotenv created
これで .env
ファイルを取り込んだので削除可能ですが、マニフェストは消してしまうことが十分考えられます。
そのため、別の場所にコピーして削除し、リポジトリからファイルを削除しておきます。
Warning
パスワードの含まれるようなファイルのですので、取り扱いには十分注意しておきましょう。
削除したら、git側に認識させ、コミットして送信しておきましょう。
コマンドライン的にgitに認識させるとこのような感じになります。
PS> git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: .env
no changes added to commit (use "git add" and/or "git commit -a")
PS> git rm .env # 削除をリポジトリ内でも処理
rm 'laravel/sample/.env'
PS> git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: .env
PS> git commit -m "[del] 環境変数ファイルの削除"
PS> git push
ところが実際に運用する際、 .env
ファイルが無いと意味がありません、
さらにマウントするときに、secretから.env
ファイルだけ切り出してここに置くのも難しいです。
そこで、 secret
のマウントは別の場所(/config
)にでも行うようにして、シンボリックリンクでごまかすことにしてみましょう。
このことを考慮すると、Dockerfile
に若干手を入れることにもなります。
FROM php
RUN --mount=type=tmpfs,destination=/var/cache/apt \
--mount=type=tmpfs,destination=/var/lib/apt \
apt-get update; \
apt-get install -y git unzip
COPY --from=composer/composer /usr/bin/composer /usr/local/bin/composer
RUN docker-php-ext-install pdo_mysql pdo
WORKDIR /var/www/html
COPY sample /var/www/html
# secretをマウントして、そこにある.envをsymlinkで見せる
RUN ln -sf /config/.env /var/www/html/.env
RUN composer install
イメージの再生成#
あとはイメージを再生成して、Docker Hubの自分のリポジトリに上げておけば使えるでしょう。
PS> cd ..
# イメージ名は自分でアクセスできれば特に問いませんが、
# タグをきちんと設定した方が良いでしょう(ここではv1)
PS> docker build -t USERNAME/larabel-sample-remastered:v1 .
PS> docker push USERNAME/larabel-sample-remastered:v1
secretをマウントしよう#
あとはマニフェストの側で、イメージが利用する場所にsecretをマウントするだけです。
# Laravelでのアプリ(frontend)
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
volumes:
- name: config
secret:
secretName: dotenv
containers:
- name: frontend
image: densukest/laravel-sample-remastered:v1
resources:
limits:
memory: "256Mi"
cpu: "500m"
ports:
- containerPort: 80
command:
- php
- artisan
- serve
- "--port=80"
- "--host=0.0.0.0"
volumeMounts:
- name: config
mountPath: /config
initContainers:
- name: init
image: densukest/laravel-sample-remastered:v1
command:
- php
- artisan
- migrate
volumeMounts:
- name: config
mountPath: /config
Caution
イメージ名(2カ所)をきちんと差し替え版イメージのリポジトリ名にしてください。
このマニフェストはbackendを参照するので、呼び出す前に必ずserviceリソース(svc-backend)も適用させてください。
PS> kubectl apply -f svc-backend.yml # service/backend(ClusterIP)
PS> kubectl apply -f frontend.yml
PS> kubectl apply -f svc-frontend.yml # service/frontend(NodePort)
...
PS> minikube service frontend # open browser