5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

EC-CUBE4をKubernetesで動かす

Last updated at Posted at 2020-12-24

最近Kubernetesを触る機会があったので、学習用にminikubeでEC-CUBEを動作させるサンプルを作ってみました。備忘も兼ねて手順を残しておこうと思います。

全体の構成

全体の構成は以下のようなイメージです。

| minikube ---------------------------------------------------
|                                                             |
| node ----------------------------------------------------|  |
|  |                                                       |  |
|  |  [ web(eccube) ] [ db(pgsql) ] [ mail(mailcatcher) ]  |  |
|  |        |                                              |  |
|  |     [ pvc ]                                           |  |
|  |        |                                              |  |
|  |     [ pv  ]                                           |  |
|  |                                                       |  |
|   --------------------------------------------------------  |
|                                                             |
 -------------------------------------------------------------

web、db(postgresql)、メール(mailcatcher)の構成で、EC-CUBEの永続化が必要なファイル群を保持する用途としてPersistentVolumeを用意しています。

前準備

minikubeのインストール

$ brew install minikube

起動しておきます

$ minikube start

MailCatcherのpodを作る

メールサーバのpodから作っていきます。

mail-deploy.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: eccube-mail
spec:
  replicas: 1
  selector:
    matchLabels:
      app: eccube-mail
  template:
    metadata:
      labels:
        app: eccube-mail
    spec:
      containers:
        - name: eccube-mail
          image: schickling/mailcatcher
          ports:
            - containerPort: 1025
            - containerPort: 1080
---
apiVersion: v1
kind: Service
metadata:
  name: eccube-mail
spec:
  type: NodePort
  selector:
    app: eccube-mail
  ports:
    - port: 1080
      targetPort: 1080
      name: mailer
    - port: 1025
      targetPort: 1025
      name: smtp

作成したマニフェストをapplyし、podを立ち上げます。

$ kubectl apply -f mail-deploy.yml 
deployment.apps/eccube-mail created
service/eccube-mail created

podの状況を確認して、StatusがRunningになっていたらOK。

$ kubectl get po
NAME                           READY   STATUS    RESTARTS   AGE
eccube-mail-5b8cf64bb9-85c5s   1/1     Running   0          83s

MailCatcherのWEBメーラを確認するには、 minikube serviceを実行します。

$ minikube service eccube-mail
|-----------|-------------|-------------|---------------------------|
| NAMESPACE |    NAME     | TARGET PORT |            URL            |
|-----------|-------------|-------------|---------------------------|
| default   | eccube-mail | mailer/1080 | http://192.168.49.2:31044 |
|           |             | smtp/1025   | http://192.168.49.2:30208 |
|-----------|-------------|-------------|---------------------------|
🏃  Starting tunnel for service eccube-mail.
|-----------|-------------|-------------|------------------------|
| NAMESPACE |    NAME     | TARGET PORT |          URL           |
|-----------|-------------|-------------|------------------------|
| default   | eccube-mail |             | http://127.0.0.1:58752 |
|           |             |             | http://127.0.0.1:58753 |
|-----------|-------------|-------------|------------------------|

上記の出力結果だと、http://127.0.0.1:58752 にアクセスし、画面が表示されることを確認します。

image.png

確認できたらminikube serviceコマンドは終了しても大丈夫です。

PostgreSQLのpodを作る

次にPostgreSQLのpodを作ります。

pgsql-deploy.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: eccube-pgsql
  labels:
    app: eccube-pgsql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: eccube-pgsql
  serviceName: eccube-pgsql
  template:
    metadata:
      labels:
        app: eccube-pgsql
    spec:
      containers:
        - image: postgres:10-alpine
          name: eccube-pgsql
          env:
            - name: POSTGRES_USER
              value: postgres
            - name: POSTGRES_PASSWORD
              value: password
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 500Mi

上記のマニフェストをapplyし、pgsqlのpodが立ち上がるのを確認します。

$ kubectl apply -f pgsql-deploy.yml
statefulset.apps/eccube-pgsql created
service/eccube-pgsql created
$ kubectl get po
NAME                           READY   STATUS    RESTARTS   AGE
eccube-mail-5b8cf64bb9-85c5s   1/1     Running   0          9m54s
eccube-pgsql-0                 1/1     Running   0          44s

webサーバのpodを作る

まず、EC-CUBEを配置するための永続ボリュームを作成します。

永続ボリュームの作成

eccube-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: eccube-pv
spec:
  storageClassName: standard
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /data/eccube
eccube-pv.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: eccube-pvc
spec:
  storageClassName: standard
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 500Mi

上記のマニフェストをapplyし、作成を確認します。


$ kubectl apply -f eccube-pv.yml -f eccube-pvc.yml
persistentvolume/eccube-pv created
persistentvolumeclaim/eccube-pvc created
$ kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS   REASON   AGE
persistentvolume/eccube-pv                                  3Gi        RWO            Retain           Bound    default/eccube-pvc            standard                2m14s
persistentvolume/pvc-fd0555f5-0bd1-4d78-b969-ba05167ac274   500Mi      RWO            Delete           Bound    default/data-eccube-pgsql-0   standard                16h

NAME                                        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/data-eccube-pgsql-0   Bound    pvc-fd0555f5-0bd1-4d78-b969-ba05167ac274   500Mi      RWO            standard       16h
persistentvolumeclaim/eccube-pvc            Bound    eccube-pv                                  3Gi        RWO            standard       113s

apacheのpodの作成

次に、apacheのpodを作成していきます。
コンテナは、eccube/php-ext-apacheを使っています。

eccube-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: eccube
spec:
  selector:
    matchLabels:
      app: eccube
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: eccube
    spec:
      containers:
        - name: eccube
          image: eccube/php-ext-apache:7.3
          volumeMounts:
            - name: htdocs-volume
              mountPath: /var/www/html
            - name: persistent-volume
              mountPath: /opt/ec-cube
      volumes:
        - name: htdocs-volume
          emptyDir: {}
        - name: persistent-volume
          persistentVolumeClaim:
            claimName: eccube-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: eccube
spec:
  type: NodePort
  selector:
    app: eccube
  ports:
    - port: 80
      targetPort: 80

上記のマニフェストをapplyし、作成を確認します。

$ kubectl apply -f eccube-deploy.yml 
deployment.apps/eccube created
service/eccube created
$ kubectl get po
NAME                           READY   STATUS    RESTARTS   AGE
eccube-bc7745978-rg64c         1/1     Running   0          98m
eccube-mail-5b8cf64bb9-85c5s   1/1     Running   0          161m
eccube-pgsql-0                 1/1     Running   0          152m

これで各pod群の準備ができました。

EC-CUBEの配置

ここからEC-CUBEの配置をしていきます。

アプリケーションによって生成・変更されるファイルがあり、そういったファイルはpodの再起動で初期化されるため、永続化することが必要になります。

今回永続化の対象にするのは以下のファイル群です。

|||永続化|
|--- | --- | --- ||
|app | Customize ||
|app | DoctrineMigrations |  
|app | Plugin | ○|
|app | PluginData | ○
|app | config |  
|app | proxy | ○
|app | template | ○
|bin |   |  
|html |   | ○
|src |   |  
|var |   | ○
|vendor |   |  
|composer.json |   | ○
|composer.lock |   | ○
|symfony.lock |   | ○
|index.php |   |  
|maintenance.php |   |  
|robots.txt |   |  
|.env |   | ○

これを元に、初期化スクリプトを作ります。

eccube_install.sh
#!/usr/bin/env bash

set -x

TMP_DIR=/tmp
ECCUBE_VER=4.0.5
ECCUBE_FILE=${TMP_DIR}/eccube-${ECCUBE_VER}.tar.gz
DOCROOT_DIR=/var/www/html
PV_DIR=/opt/ec-cube

cd ${TMP_DIR}
curl -O https://downloads.ec-cube.net/src/eccube-${ECCUBE_VER}.tar.gz

if [ -d ${DOCROOT_DIR} ]; then
  rm -rf ${DOCROOT_DIR}
  mkdir -p ${DOCROOT_DIR}
fi

# document root配下に展開
cd ${DOCROOT_DIR}
tar xvzf ${ECCUBE_FILE} --strip-components 1

rm -rf ${DOCROOT_DIR}/composer.json
rm -rf ${DOCROOT_DIR}/composer.lock
rm -rf ${DOCROOT_DIR}/symfony.lock
rm -rf ${DOCROOT_DIR}/app/Plugin
rm -rf ${DOCROOT_DIR}/app/PluginData
rm -rf ${DOCROOT_DIR}/app/template
rm -rf ${DOCROOT_DIR}/html
rm -rf ${DOCROOT_DIR}/var

# link作成
ln -s ${PV_DIR}/.env ${DOCROOT_DIR}/.env
ln -s ${PV_DIR}/composer.json ${DOCROOT_DIR}/composer.json
ln -s ${PV_DIR}/composer.lock ${DOCROOT_DIR}/composer.lock
ln -s ${PV_DIR}/symfony.lock ${DOCROOT_DIR}/symfony.lock
ln -s ${PV_DIR}/app/Plugin ${DOCROOT_DIR}/app/Plugin
ln -s ${PV_DIR}/app/PluginData ${DOCROOT_DIR}/app/PluginData
ln -s ${PV_DIR}/app/template ${DOCROOT_DIR}/app/template
ln -s ${PV_DIR}/html ${DOCROOT_DIR}/html
ln -s ${PV_DIR}/var ${DOCROOT_DIR}/var

# 永続ボリュームへ展開
cd ${PV_DIR}
ARCHIVE_ROOT=$(tar tf ${ECCUBE_FILE} | sort | head -n 1)

if [ ! -f ${PV_DIR}/.env ]; then

  cat << EOF > .env
APP_ENV=${APP_ENV}
APP_DEBUG=${APP_DEBUG}
DATABASE_URL=${DATABASE_URL}
DATABASE_SERVER_VERSION=${DATABASE_SERVER_VERSION}
MAILER_URL=${MAILER_URL}
ECCUBE_AUTH_MAGIC=${ECCUBE_AUTH_MAGIC}
ECCUBE_ADMIN_ROUTE=${ECCUBE_ADMIN_ROUTE}
EOF

  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}composer.json --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}composer.lock --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}symfony.lock --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}app/Plugin --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}app/PluginData --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}app/template --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}html --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}var --strip-components 1

  cd ${DOCROOT_DIR}
  bin/console e:i --no-interaction

else

  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}composer.json --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}composer.lock --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}symfony.lock --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}vendor --strip-components 1
  tar xfz ${ECCUBE_FILE} ${ARCHIVE_ROOT}html --strip-components 1

  cd ${DOCROOT_DIR}
  bin/console cache:clear --no-warmup --env=prod
  bin/console eccube:composer:require-already-installed
  bin/console doctrine:schema:update --force --dump-sql
  bin/console doctrine:migrations:migrate --no-interaction

fi

bin/console cache:clear --no-warmup --env=prod
bin/console cache:warmup --no-optional-warmers --env=prod
composer dump-autoload -o

chown -R www-data:www-data ${PV_DIR}
chown -R www-data:www-data ${DOCROOT_DIR}

DocumentRoot直下は毎回クリア・ソースコードが展開され、永続化されている/opt/ec-cubeへシンボリックリンクを貼る構成にしています。

また、初回起動時はEC-CUBEのインストールを実行し、2回目以降はスキーマ更新やマイグレーションを行います。

このスクリプトをpod初期化時に実行できるよう、コンテナ化します。

Dockerfile
FROM eccube/php-ext-apache:7.3

ADD eccube_install.sh /

ローカルのDockerイメージにminikubeからアクセスできるよう、ビルド前に以下を実行します。

$ eval $(minikube -p minikube docker-env)

ビルドします。

$ docker build . -t local/eccube-maintenance

初期化スクリプトの用意はできたので、apacheのpod初期化時に実行されるよう、eccube-deploy.ymlを以下のように修正します。

eccube-deploy.yml
apiVersion: apps/v1
...
    spec:
+      initContainers:
+        - name: eccube-init
+          image: local/eccube-maintenance:latest
+          imagePullPolicy: IfNotPresent
+          envFrom:
+            - configMapRef:
+                name: eccube-config
+          volumeMounts:
+            - name: htdocs-volume
+              mountPath: /var/www/html
+            - name: persistent-volume
+              mountPath: /opt/ec-cube
+          command: ["/eccube_install.sh"]
      containers:
        - name: eccube
          image: eccube/php-ext-apache:7.3
          volumeMounts:
            - name: htdocs-volume
              mountPath: /var/www/html
            - name: persistent-volume
              mountPath: /opt/ec-cube
...

また、EC-CUBEの初期化時に渡す環境変数を定義しておきます

eccube-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: eccube-config
data:
  APP_ENV: 'prod'
  APP_DEBUG: '0'
  DATABASE_URL: 'postgresql://postgres:password@eccube-pgsql:5432/eccube.db'
  DATABASE_SERVER_VERSION: '10'
  MAILER_URL: 'smtp://eccube-mail:1025'
  ECCUBE_ADMIN_USER: 'admin'
  ECCUBE_ADMIN_PASS: 'password'
  ECCUBE_AUTH_MAGIC: 'Myvpx7CecbURw9cF'
  ECCUBE_ADMIN_ROUTE: 'admin'

上記のマニフェストをapplyします。

$ kubectl apply -f eccube-config.yml -f eccube-deploy.yml
configmap/eccube-config created
deployment.apps/eccube configured
service/eccube unchanged

動作確認

minikube service eccube でEC-CUBEの動作確認をします。
ブラウザでEC-CUBEの画面が立ち上がれば成功です。

$ minikube service eccube
|-----------|--------|-------------|---------------------------|
| NAMESPACE |  NAME  | TARGET PORT |            URL            |
|-----------|--------|-------------|---------------------------|
| default   | eccube |          80 | http://192.168.49.2:30541 |
|-----------|--------|-------------|---------------------------|
🏃  Starting tunnel for service eccube.
|-----------|--------|-------------|------------------------|
| NAMESPACE |  NAME  | TARGET PORT |          URL           |
|-----------|--------|-------------|------------------------|
| default   | eccube |             | http://127.0.0.1:62911 |
|-----------|--------|-------------|------------------------|
🎉  Opening service default/eccube in default browser...
❗  Dockerドライバーをdarwin上で動かしているため、実行するにはターミナルを開く必要があります。

image.png

以上になります。

マニフェストやDockerfileはこちらにも上げていますので、参考にしていただければ幸いです。

5
3
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
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?