Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

KubernetesでDockerコンテナ「php:7.0-apache」を利用してみる

More than 1 year has passed since last update.

概要

Dockerコンテナphp:7.0-apacheをminikubeを使って構築したkubernetes環境にdeployし、WEBブラウザからページが閲覧できるようにしてみる。

目次

関連記事

環境

  • CentOS 7.6
  • Minikube v1.1.1
  • Kubernetes v1.14.3

minikube(クラスタ)起動

まずはクラスタ起動

$ sudo /usr/local/bin/minikube start --vm-driver=none

DockerHubで公開されているphp:7.0-apacheをdeployする

podを定義

pod.yml
apiVersion: v1
kind: Pod
metadata:
  # pod名
  name: sample-web-pod
  labels:
    app: http-app
spec:
  containers:
    # Dockerコンテナ名
    - name: web-container
      # 利用するDockerイメージ
      image: php:7.0-apache
      # コンテナ内のport
      ports:
        - name: http-port
          containerPort: 80
      # mountするディレクトリ:コンテナ側の設定
      volumeMounts:
        - name: documentroot
          mountPath: /var/www/html
  # mountするディレクトリ:ホストOS側の設定
  volumes:
    - name: documentroot
      hostPath:
        path: /home/username/containers/web/html

serviceを定義

service.yml
kind: Service
apiVersion: v1
metadata:
  # service名
  name: http-service
  labels:
    app: http-app
spec:
  selector:
    app: http-app
  # 公開するport
  ports:
    - port: 8080
      targetPort: http-port
  type: NodePort

pod、serviceを作成

$ sudo kubectl create -f pod.yml -f service.yml

curlでwebアクセス

http-serviceにアクセスしてみる

$ curl $(sudo minikube service http-service --url)
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /
on this server.<br />
</p>
<hr>
<address>Apache/2.4.25 (Debian) Server at xxx.xxx.xxx.xxx Port 32016</address>
</body></html>

ブラウザからアクセス

URLを取得

$ sudo minikube service http-service --url
http://xxx.xxx.xxx.xxx:32016

ApacheのForbiddenページが表示されればOK。

index.phpを作成

mountした領域にindex.phpを作成

/home/username/containers/web/html/index.php
<?php phpinfo(); ?>

URLを取得

$ sudo minikube service http-service --url
http://xxx.xxx.xxx.xxx:32016

ブラウザからhttp://xxx.xxx.xxx.xxx:32016 にアクセス
<?php phpinfo(); ?>の内容が表示されればOK。

podの状態を確認

$ sudo kubectl describe pod sample-web-pod
# **snip**
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  2s    default-scheduler  Successfully assigned default/sample-web-pod to minikube
  Normal  Pulling    2s    kubelet, minikube  Pulling image "php:7.0-apache"

serviceの状態を確認

$ sudo kubectl get services
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
http-service   NodePort    10.109.95.198   <none>        8080:32269/TCP   7m41s
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP          7h4m

localのDockerイメージを利用する場合

local(ホストOS上)のDockerイメージを利用しようとすると、イメージをpullすることができず、以下のエラーが出る。

$ sudo minikube logs -f
container start failed: ErrImagePull: rpc error: code = Unknown desc = Error response from daemon: repository my-web-server not found: does not exist or no pull access

イメージがpullできないということは、当然コンテナが立ち上がらないのでアクセスできない。

$ curl `sudo minikube service http-service --url`
curl: (7) Failed connect to xxx.xxx.xxx.xxx:31528; Connection refused

コンテナにも入れない。

$ sudo kubectl exec sample-web-pod /bin/sh
error: unable to upgrade connection: container not found ("web-container")

podをdescribeすることでもエラーを確認できる。

$ sudo kubectl describe pod sample-web-pod
# **snip**
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  10m                  default-scheduler  Successfully assigned default/sample-web-pod to minikube
  Normal   Pulling    9m4s (x4 over 10m)   kubelet, minikube  Pulling image "web-container:latest"
  Warning  Failed     9m2s (x4 over 10m)   kubelet, minikube  Failed to pull image "web-container:latest": rpc error: code = Unknown desc = Error response from daemon: repository web-container not found: does not exist or no pull access
  Warning  Failed     9m2s (x4 over 10m)   kubelet, minikube  Error: ErrImagePull
  Warning  Failed     8m38s (x6 over 10m)  kubelet, minikube  Error: ImagePullBackOff
  Normal   BackOff    32s (x41 over 10m)   kubelet, minikube  Back-off pulling image "web-container:latest"

解決策

minikubeでローカルのdocker imageを使う

以下コマンドで、minikube VM上のDockerイメージを使うように設定できる。

$ eval $(sudo minikube docker-env)

これにより以下が設定される。

  • DOCKER_TLS_VERIFY
  • DOCKER_HOST
  • DOCKER_CERT_PATH
  • DOCKER_API_VERSION

--vm-driver=noneでminikubeを起動している場合

sudo minikube docker-envを実行すると以下のエラーが出る。

'none' driver does not support 'minikube docker-env' command

--vm-driver=noneでminikubeを起動している場合、$(minikube docker-env)は利用できない。
そもそも、localにイメージが存在しているので、pullする必要がない。

参考:https://github.com/kubernetes/minikube/issues/2575#issuecomment-410145576

your locally available images are also available to kubernetes with vm-driver=none.

Not that I'm aware of. Note that you don't even have to pull them: with vm-driver=none it's the same docker daemon as on your desktop

pod.ymlのDockerイメージの定義部分で、imagePullPolicyを指定することで、localのDockerイメージを利用することができるようになる。

  • imagePullPolicy: IfNotPresent
    • localイメージ利用。ただし、localに指定したイメージが存在しない場合はレポジトリを参照する。
  • imagePullPolicy: Never
    • localイメージのみを利用。

自作Dockerイメージを作成

以上を踏まえて、自作Dockerイメージを作成し、pod、serviceを作成してみる。

Dockerfile
From php:7.0-apache

buildする。
タグをlatestにすると、k8sはrepositoryからpullしようとしてしまうので、versionを明記する。

$ sudo docker build -t my-web-server:v1.0 ./

pod.ymlを定義

今回はimagePullPolicy: Neverを指定する。

pod.yml
apiVersion: v1
kind: Pod
metadata:
  # pod名
  name: sample-web-pod
  labels:
    app: http-app
spec:
  containers:
    # Dockerコンテナ名
    - name: web-container
      # 利用するDockerイメージ
-     image: php:7.0-apache
+     # localの自作イメージ
+     image: my-web-server:v1.0
+     imagePullPolicy: Never
+     #imagePullPolicy: IfNotPresent
      # コンテナ内のport
      ports:
        - name: http-port
          containerPort: 80
      # mountするディレクトリ:コンテナ側の設定
      volumeMounts:
        - name: documentroot
          mountPath: /var/www/html
  # mountするディレクトリ:ホストOS側の設定
  volumes:
    - name: documentroot
      hostPath:
        path: /home/username/containers/web/html

service.yml

先程と同じ

pod、serviceを作成

$ sudo kubectl create -f pod.yml -f service.yml

podの状態を確認

$ sudo kubectl describe pod sample-web-pod
# **snip**
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  3s    default-scheduler  Successfully assigned default/sample-web-pod to minikube
  Normal  Pulled     2s    kubelet, minikube  Container image "my-web-server:v1.0" already present on machine
  Normal  Created    2s    kubelet, minikube  Created container web-container-name
  Normal  Started    2s    kubelet, minikube  Started container web-container-name
$ sudo kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
sample-web-pod   1/1     Running   0          23s

webアクセス

$ curl $(sudo minikube service http-service --url)
# omitted...
# <?php phpinfo(); ?>の内容が表示されればOK

ブラウザからアクセス

URLを取得

$ sudo minikube service http-service --url
http://xxx.xxx.xxx.xxx:30910

ブラウザから http://xxx.xxx.xxx.xxx:30910 にアクセスして、<?php phpinfo(); ?>の内容が表示されればOK

Delete

$ sudo kubectl delete services http-service
$ sudo kubectl delete pods sample-web-pod

参考

Esfahan
WEB系出身。現在はビッグデータの基盤構築、ETLなどがメイン。 / YouTubeで料理チャンネルやってます → https://www.youtube.com/channel/UCDnYBh2TtUAfQ0Z-tl0jTyw
https://www.youtube.com/channel/UCDnYBh2TtUAfQ0Z-tl0jTyw
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away