CLOVER🍀

That was when it all began.

OKD/Minishiftで、Dockerイメージを(作って)デプロイするいろいろ

これは、なにをしたくて書いたもの?

  • OKD(OpenShift)を使って、Dockerイメージをデプロイする方法をまとめておこうかと思って
  • 直接Dockerイメージをデプロイしたり、Dockerfileからビルドしてデプロイする方法もあるので、そちらも合わせて

Templateを使うパターンは、今回は置いておきます。

環境

今回の環境は、こちらです。

$ minishift version
minishift v1.31.0+cfc599c


$ oc version
oc v3.11.0+0cbc58b
kubernetes v1.11.0+d4cacc0
features: Basic-Auth GSSAPI Kerberos SPNEGO

Server https://192.168.42.112:8443
kubernetes v1.11.0+d4cacc0

「oc new-app」

基本は、こちらです。

Creating New Applications - Application Life Cycle Management | Developer Guide | OKD 3.11

Dockerイメージをデプロイする

まずは、すでに存在するDockerイメージをデプロイする方法から。

Creating an Application From an Image

例えば、DockerHubにあるSonatype Nexus 3のDockerイメージをデプロイ。

$ oc new-app sonatype/nexus3:3.15.2

Sonatype Nexus 3

Routeを追加。

$ oc expose svc/nexus3

確認。

$ curl -I nexus3-myproject.192.168.42.112.nip.io
HTTP/1.1 200 OK
Date: Sat, 09 Feb 2019 06:24:23 GMT
Server: Nexus/3.15.2-01 (OSS)
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Type: text/html
Last-Modified: Sat, 09 Feb 2019 06:24:23 GMT
Pragma: no-cache
Cache-Control: post-check=0, pre-check=0
Expires: 0
Content-Length: 7085
Set-Cookie: 38db5894cd3f4d4cfad3c49452da8aee=8b9c65053c75611e79740b706923b345; path=/; HttpOnly

OKDにデプロイする場合は、なにも考えずにrootで起動するコンテナをデプロイすると、うまく起動できなかったりするので
注意しましょう。

ソースコードを含むGitリポジトリからデプロイする

続いて、アプリケーションのソースコードを含むGitリポジトリからDockerイメージを作って、デプロイする方法。

Creating an Application From Source Code

今回は、Node.js+Expressでサンプルアプリケーションを作ります。

$ npm i express

依存関係。

  "dependencies": {
    "express": "^4.16.4"
  }

作成したコード。アクセスすると、実行中のNode.jsのバージョンを返却するようにしています。

server.js

const express = require("express");
const app = express();

app.get("/", (req, res) => {
    res.send(`Node.js version = ${process.version}`);
});

console.log(`[${new Date()}] server startup`);

app.listen(8080);

これを、「npm start」で実行できるようにしてGitリポジトリに登録します。

  "scripts": {
    "start": "node server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

デプロイ。「--name」は省略すると、リポジトリ名から付与されますが、今回は明示。

$ oc new-app --name simple-nodejs-app http://〜[GitリポジトリへのURL]

イメージを作成する際に、どの言語としてビルドするのかはある程度自動判別してくれます。

言語の判定のルールは、こちら。

Language Detection

では、確認用にRouteを作成。

$ oc expose svc/simple-nodejs-app

確認。

$ curl simple-nodejs-app-myproject.192.168.42.112.nip.io
Node.js version = v10.12.0

Node.js 10.12.0で動作していることが確認できました。

ソースコードを含むGitリポジトリからデプロイする(ビルド時に使用するイメージを指定する)

ところで、OKD 3.11で使えるNode.jsのバージョンはこれだけです。今回は、Node.jsの10が選ばれたことになります。

$ oc get is/nodejs -n openshift -o json | jq '.spec.tags[].name'
"0.10"
"10"
"4"
"6"
"8"
"8-RHOAR"
"latest"

ビルド時に使うイメージを変えて、デプロイしてみましょう。Node.jsのバージョンは、8を使うことにします。

## 「-i」または「--image-stream」でNode.js 8を指定
$ oc new-app --name simple-nodejs-app -i nodejs:8 http://〜[GitリポジトリへのURL]

## または、GitリポジトリのURLの前に「使うイメージ~」を付ける
$ oc new-app --name simple-nodejs-app nodejs:8~http://〜[GitリポジトリへのURL]

Route作成後、確認。どちらの方法でデプロイしても結果は同じなので、片方だけ。

$ oc expose svc/simple-nodejs-app
$ curl simple-nodejs-app-myproject.192.168.42.112.nip.io
Node.js version = v8.11.4

ソースコードを含むGitリポジトリからデプロイする(Dockerfileを使う)

また、GitリポジトリにDockerfileを入れておくと、Dockerfileからビルドしてイメージを作ってくれます。

今回は、このようなDockerfileを用意して、Gitリポジトリに追加しておきます。OKDに入っていない、Node.js 11のイメージを使います。
Dockerfile

FROM node:11.9.0

COPY . /opt/app
RUN cd /opt/app && \
    npm i && \
    chgrp -R 0 /opt/app && \
    chmod -R g=u /opt/app

USER 1001
WORKDIR /opt/app
EXPOSE 8080

ENTRYPOINT [ "npm", "start" ]

最初、EXPOSEを書くのを忘れて、Serviceが自動的に作られなくてハマりました…。

uidや権限の指定方法は、こちらを参考に。

OKD-Specific Guidelines

では、デプロイ。

$ oc new-app --name simple-nodejs-app http://〜[GitリポジトリへのURL]

この時、Dockerfileで指定したイメージを使っていることがわかります。

--> Found Docker image 9ba05fb (3 days old) from Docker Hub for "node:11.9.0"

Routeを作成して、確認。

$ oc expose svc/simple-nodejs-app
$ curl simple-nodejs-app-myproject.192.168.42.112.nip.io
Node.js version = v11.9.0

Node.js 11上で動いていますね。

なお、Dockerfileが入った状態でもソースコードからイメージをビルドしたい場合は、「strategy」オプションで「source」を
指定すればOKです。

$ oc new-app --name simple-nodejs-app --strategy=source http://〜[GitリポジトリへのURL]

Dockerfileを使うことを明示する場合は、「docker」を指定します。

$ oc new-app --name simple-nodejs-app --strategy=docker http://〜[GitリポジトリへのURL]

strategyオプションについては、こちらを参照。

Build Strategy Detection

インラインDockerfileからビルド・デプロイする

最後は、インラインDockerfileからイメージをビルドして、デプロイするところまで。

Dockerfile Source

この場合、「new-app」ではなく、「new-build」でイメージを作成してからデプロイすることになります。

こんなDockerfileを用意。
Dockerfile

FROM ubuntu:18.04

RUN apt-get update -y && apt-get install -y python3 && apt-get clean

USER 1001
EXPOSE 8000

ENTRYPOINT [ "python3", "-m", "http.server" ]

Dockerイメージをビルド。「--dockerfile」オプションに「-」を指定することで、標準入力からDockerfileの定義を読み込むことが
できます。

$ cat Dockerfile | oc new-build --name simple-python-httpserver --dockerfile=-

アプリケーションとして、デプロイ。

$ oc new-app simple-python-httpserver

Routeを作成して、確認。

$ oc expose svc/simple-python-httpserver
$ curl simple-python-httpserver-myproject.192.168.42.112.nip.io
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ascii">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".dockerenv">.dockerenv</a></li>
<li><a href="bin/">bin/</a></li>
<li><a href="boot/">boot/</a></li>
<li><a href="dev/">dev/</a></li>
<li><a href="etc/">etc/</a></li>
<li><a href="home/">home/</a></li>
<li><a href="lib/">lib/</a></li>
<li><a href="lib64/">lib64/</a></li>
<li><a href="media/">media/</a></li>
<li><a href="mnt/">mnt/</a></li>
<li><a href="opt/">opt/</a></li>
<li><a href="proc/">proc/</a></li>
<li><a href="root/">root/</a></li>
<li><a href="run/">run/</a></li>
<li><a href="sbin/">sbin/</a></li>
<li><a href="srv/">srv/</a></li>
<li><a href="sys/">sys/</a></li>
<li><a href="tmp/">tmp/</a></li>
<li><a href="usr/">usr/</a></li>
<li><a href="var/">var/</a></li>
</ul>
<hr>
</body>
</html>

なお、DockerfileをBuildConfigを定義するYAMLに書いて、実行することもできます。

Dockerfile Source

Binary Build

最後に、Binary Build。Dockerfileを使用します。

Binary Builds - Tutorials | Developer Guide | OKD 3.11

Binary Buildを使用することで、ローカルファイルをOKDに転送して、Gitリポジトリを使わずにビルドを行うことができます。

これを使うと、GitリポジトリにpushしたりしなくてもDockerイメージのビルドができるようになります。

ですが、Binary Buildを使うには各ビルド時にユーザーがファイルをアップロードしなければなりません。つまり、都度同じファイルを
アップロードしないと、ビルドに再現性がなくなります。また、ユーザーによるファイルのアップロードを伴うので、ビルドの自動起動も
できなくなります。

このあたりに注意して、使っていきましょう。

ファイルは、先ほど作成した、Node.jsのサンプルアプリケーションを使います。ファイルは、これだけ残しました。

$ ls -1
Dockerfile
package-lock.json
package.json
server.js

あとは、こちらに従ってビルドし、アプリケーションをデプロイします。

Tutorial: Building private code

ビルドの定義。

$ oc new-build --strategy docker --binary --name simple-nodejs-app

カレントディレクトリ(「.」)の内容を転送して、ビルド開始。

$ oc start-build simple-nodejs-app --from-dir .

デプロイ、Route作成、確認。

$ oc new-app simple-nodejs-app
$ oc expose svc/simple-nodejs-app
$ curl simple-nodejs-app-myproject.192.168.42.112.nip.io
Node.js version = v11.9.0

つまり、ビルドの度に毎回これをやることになる、というわけですね。

$ oc start-build simple-nodejs-app --from-dir .

今回はいろんな方法でOKD上でのDockerイメージのビルド、デプロイを試してみましたが、使ったことがないものも
あったので勉強になりました。