はじめに
OpenShiftの環境では、Dockerイメージからコンテナを起動する際に(主にセキュリティ上の理由から)いくつかの制限がかけられるため、一定のお作法に従ってイメージを作成しておく必要があります。ここでは、そのようなイメージを作成して、OpenShiftの環境で実行する手順を紹介します。
(参考資料)
・Fwd: openshift-nginx docker image running as non-root
nginxのイメージの例
特に大きな注意点として、コンテナ内のプロセスはrootユーザーでの実行が禁止されます。一般に、Dockerfileに「USER」指定がない場合、rootユーザーでプロセスが起動されますが、OpenShiftの環境ではこれが禁止されているために、コンテナの起動に失敗します。さらに、「USER」指定を行った場合でも、実際にプロセスを起動するUIDは、OpenShiftによって任意に選択されます。そのため、Dockerfileで作成するイメージは、「USER」指定を入れた上で、さらに、「任意の一般ユーザーで実行できる」ように設計しておく必要があります。具体的には、設定ファイルや実行バイナリーには、chmodコマンドで「ugo」に対するアクセス権を設定しておきます。
他には、細かい点ですが、「docker run」には「-d」オプションのみが指定される(「-it」オプションは指定されない)ため、仮想TTYを必要とするコマンド(bashなど)は実行できません。
以上のお作法にのっとった、nginxのDockerイメージを作成するDokcerfileの例が下記になります。
・nginx with arbitrary non-root users
「OpenShift OriginによるDockerイメージ管理(2)〜Dockerfileによるイメージビルドを自動化」で紹介した方法で、これからDockerイメージをビルドして、イメージストリームに登録しておきます。
nginx-sample_is.yml
apiVersion: v1 kind: ImageStream metadata: name: nginx-sample
nginx-sample_bc.yml
apiVersion: v1 kind: BuildConfig metadata: name: nginx-sample spec: output: to: kind: ImageStreamTag name: nginx-sample:latest source: git: uri: https://github.com/enakai00/openshift_nginx_sample type: Git strategy: dockerStrategy: from: kind: ImageStreamTag name: centos7:latest type: Docker triggers: - imageChange: {} type: ImageChange
# oc login -u enakai # oc delete project project01 # oc new-project project01 --description="Project to learn creating Docker images" --display-name="Learning Docker Image Development" # docker pull centos:7 # docker login -u enakai -e enakai@example.com -p $(oc whoami -t) registry.oso.example.com # docker tag docker.io/centos:7 registry.oso.example.com/project01/centos7:latest # docker push registry.oso.example.com/project01/centos7:latest # oc create -f nginx-sample_is.yml # oc get is NAME DOCKER REPO TAGS UPDATED centos7 172.30.84.64:5000/project01/centos7 latest 31 seconds ago nginx-sample 172.30.84.64:5000/project01/nginx-sample # oc create -f nginx-sample_bc.yml # oc start-build nginx-sample nginx-sample-1 # oc logs -f build/nginx-sample-1 ... I1229 23:38:38.193339 1 docker.go:86] Pushing image 172.30.84.64:5000/project01/nginx-sample:latest ... I1229 23:39:18.956971 1 docker.go:90] Push successful # oc describe bc nginx-sample Name: nginx-sample Created: About a minute ago Labels: <none> Latest Version: 1 Strategy: Docker Source Type: Git URL: https://github.com/enakai00/openshift_nginx_sample From Image: ImageStreamTag centos7:latest Output to: ImageStreamTag nginx-sample:latest Triggered by: ImageChange Build Status Duration Creation Time nginx-sample-1 complete 1m7s 2015-12-30 08:38:16 +0900 JST # oc describe is nginx-sample Name: nginx-sample Created: 3 minutes ago Labels: <none> Annotations: openshift.io/image.dockerRepositoryCheck=2015-12-29T23:36:50Z Docker Pull Spec: 172.30.84.64:5000/project01/nginx-sample Tag Spec Created PullSpec Image latest <pushed> 50 seconds ago 172.30.84.64:5000/project01/nginx-sample@sha256:a570779c87525781651f80853890353e622b15be47daa1c3b90f027cff8a1392
イメージストリームからコンテンを起動
イメージストリームに登録されたDockerイメージを使ってコンテナを起動するには、「デプロイ設定(DeploymentConfig)」を利用します。次が定義ファイルの例になります。
nginx-sample_dc.yml
apiVersion: v1 kind: DeploymentConfig metadata: name: nginx-sample spec: template: metadata: labels: name: nginx-sample spec: containers: - name: nginx-sample-latest image: nginx-sample:latest ports: - containerPort: 8080 protocol: TCP replicas: 1 selector: name: nginx-sample triggers: - type: ImageChange imageChangeParams: automatic: true containerNames: - nginx-sample-latest from: kind: ImageStreamTag name: nginx-sample:latest - type: ConfigChange
「template:」部分に起動するコンテナの情報(テンプレート)を記載します。「image:」の部分に使用するイメージを指定しますが、ここに記載した名称はダミーのものです。この部分は、「triggers:」によって、イメージストリームのタグで指定されるイメージで上書きされます。「triggers:」は、コンテナを再デプロイするトリガーを指定するもので、ここでは、「type: ImageChange」の「from:」部分でイメージストリームのタグ「nginx-sample:latest」が変化したら再デプロイするという指定を行っています。これにより、イメージストリームのタグで指定されるイメージからコンテナの起動が行われます。(これがないと、ダミー指定が上書きされず、Docker Hubの「nginx-sample:latest」を探しに行ってしまいます。)また、イメージの再ビルドによって、「nginx-sample:latest」が新しいイメージを指すと自動的に再デプロイが行われます。最後の「type: ConfigChange」は、デプロイ設定を変更したら自動で再デプロイするという指定です。これがあると、デプロイ設定を定義するとすぐにコンテナの起動が開始します。(デプロイ設定の定義そのものも、デプロイ設定の変更とみなされるためです。)
なお、「template:」に複数のコンテナを指定すると、これらは同一のPod(仮想NICを共有したコンテナ群)で起動します。「replicas:」と「selector:」は、指定のテンプレートから指定の数のPodを起動します。複数起動した場合は、自動でロードバランスが行われます。
それでは実際にデプロイ設定(dc)を投入します。
# oc create -f nginx-sample_dc.yml # oc get dc NAME TRIGGERS LATEST nginx-sample ConfigChange, ImageChange 1 # oc describe dc nginx-sample Name: nginx-sample Created: 10 seconds ago Labels: <none> Latest Version: 1 Triggers: Image(nginx-sample@latest, auto=true), Config Strategy: Rolling Template: Selector: name=nginx-sample Replicas: 1 Containers: NAME IMAGE ENV nginx-sample-latest 172.30.84.64:5000/project01/nginx-sample@sha256:a570779c87525781651f80853890353e622b15be47daa1c3b90f027cff8a1392 Deployment #1 (latest): Name: nginx-sample-1 Created: 10 seconds ago Status: Running Replicas: 1 current / 1 desired Selector: deployment=nginx-sample-1,deploymentconfig=nginx-sample,name=nginx-sample Labels: openshift.io/deployment-config.name=nginx-sample Pods Status: 0 Running / 1 Waiting / 0 Succeeded / 0 Failed No events. # oc get pod NAME READY STATUS RESTARTS AGE nginx-sample-1-build 0/1 Completed 0 13m nginx-sample-1-deploy 1/1 Running 0 17s nginx-sample-1-omrw1 0/1 Pending 0 13s
「nginx-sample-1-deploy」は、デプロイ処理をキックするためのコンテナです。この中で、「dokcer pull」などの準備処理が行われます。「nginx-sample-1-omrw1」が実際に起動されるコンテナです。コンテナが無事に起動すると、「nginx-sample-1-deploy」は消滅します。
# oc get pods NAME READY STATUS RESTARTS AGE nginx-sample-1-build 0/1 Completed 0 17m nginx-sample-1-omrw1 1/1 Running 0 4m
次のコマンドで、起動したコンテナの詳細が確認できます。
# oc describe pod nginx-sample-1-omrw1
コンテナ内のアプリケーションへのアクセス
コンテナで起動したアプリケーションにアクセスするには、「サービス(Service)」と「ルーティング(Route)」を定義する必要が有ります。サービスは他のコンテナからのアクセスを許可するもので、ルーティングは外部ネットワークからのアクセスを許可するものになります。
まず、次の定義ファイルでサービス(svc)を設定します。
nginx-sample_svc.yml
apiVersion: v1 kind: Service metadata: name: nginx-sample spec: ports: - name: 8080-tcp protocol: TCP port: 8080 targetPort: 8080 selector: deploymentconfig: nginx-sample
# oc create -f nginx-sample_svc.yml # oc get svc NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE nginx-sample 172.30.137.89 <none> 8080/TCP deploymentconfig=nginx-sample 5s
これで、他のコンテナからは、「172.30.137.89:8080」でアクセス可能になります。マスターからもこのIPで直接にアクセス可能です。
# curl http://172.30.137.89:8080 Hello, World!
続いて、次の定義ファイルでルーティング(route)を設定します。
nginx-sample_route.yml
apiVersion: v1 kind: Route metadata: name: nginx-sample-route spec: host: nginx-sample.project01.oso.example.com to: kind: Service name: nginx-sample
# oc create -f nginx-sample_route.yml # oc get route NAME HOST/PORT PATH SERVICE LABELS INSECURE POLICY TLS TERMINATION nginx-sample-route nginx-sample.project01.oso.example.com nginx-sample
これで外部からは、「http://nginx-sample.project01.oso.example.com」でアクセス可能になりました。
# curl http://nginx-sample.project01.oso.example.com Hello, World!
なお、複数の定義をひとつのファイルにまとめることも可能です。「kind: List」を用いて、次のように記述します。
nginx-sample_access.yml
apiVersion: v1 kind: List items: - apiVersion: v1 kind: Service metadata: name: nginx-sample spec: ports: - name: 8080-tcp protocol: TCP port: 8080 targetPort: 8080 selector: deploymentconfig: nginx-sample - apiVersion: v1 kind: Route metadata: name: nginx-sample-route spec: host: nginx-sample.project01.oso.example.com to: kind: Service name: nginx-sample
これを用いると、次のコマンドで、サービスとルーティングをまとめて設定することができます。
# oc create -f nginx-sample_access.yml
外部レジストリーのイメージを使用する方法
Docker Hubなどの外部レジストリーでも、OpenShiftで実行可能なDockerイメージが公開されています。これらを利用する場合、一度、内部レジストリーにPushしてイメージストリームに登録する他に、イメージストリームのタグ機能を用いて、イメージストリームから直接に外部レジストリーのイメージを参照することも可能です。
# oc tag --source=docker centos/postgresql-94-centos7:latest postgresql:9.4 # oc tag postgresql:9.4 postgresql:latest --alias # oc describe is postgresql Name: postgresql Created: 11 seconds ago Labels: <none> Annotations: openshift.io/image.dockerRepositoryCheck=2015-12-30T11:27:13Z Docker Pull Spec: 172.30.84.64:5000/project01/postgresql Tag Spec Created PullSpec Image 9.4 centos/postgresql-94-centos7:latest 9 seconds ago docker.io/centos/postgresql-94-centos7@sha256:1ac41adb8b746bef67f289f86bcbed6afed50dd745e46371a562a4af8cb0b14c latest postgresql:9.4 9 seconds ago docker.io/centos/postgresql-94-centos7@sha256:1ac41adb8b746bef67f289f86bcbed6afed50dd745e46371a562a4af8cb0b14c
この例では、イメージストリーム「postgresql:latest」もしくは「postgresql:9.4」から、Docker Hub上のイメージ「centos/postgresql-94-centos7:latest」を参照することが可能になります。「--alias」オプションは、「postgresql:latest」は、常に「postgresql:9.4」と同じイメージを指すように指定します。