OpenShiftのSource to Imageの理解のため、GoのカスタムS2Iイメージを作成し、Minishiftで動かしてみたメモ。
Minishiftを動かすまでは以下を参考。
コンポーネント | バージョン |
---|---|
Minishift | v1.34.1+c2ff9cb |
OpenShift | v3.11.0 |
s2i | v1.1.14-dirty |
準備
Minishiftを起動しておく。
minishift start
s2iコマンドをインストールしておく。
brew install source-to-image
S2Iビルダーイメージの作成
s2i
コマンドで雛形を作成する。
s2i create custom-go-s2i custom-go-s2i
作成されたファイルを確認。
$ tree -a custom-go-s2i
custom-go-s2i
├── Dockerfile
├── Makefile
├── README.md
├── s2i
│ └── bin
│ ├── assemble
│ ├── run
│ ├── save-artifacts
│ └── usage
└── test
├── run
└── test-app
└── index.html
4 directories, 9 files
$
assemble
、run
を編集する。usage
はそのまま使う。save-artifacts
は今回は使わないので削除する。
ファイル | 説明 |
---|---|
assemble | ソースからアプリをビルドして適切な場所に配置する。 |
run | DockerfileのCMDとして実行される。 |
save-artifacts | キャッシュを使ってビルドを早くしたいときに使う。 |
usage | イメージの使い方の説明を書く。 |
#!/bin/bash -e
# If the 'custom-go-s2i' assemble script is executed with the '-h' flag, print the usage.
if [[ "$1" == "-h" ]]; then
exec /usr/libexec/s2i/usage
fi
echo "---> Installing application source..."
cp -Rf /tmp/src/. /opt/app-root/
echo "---> Building application from source..."
XDG_CACHE_HOME=/tmp/.cache go build app.go
#!/bin/bash -e
exec /opt/app-root/app
#!/bin/bash -e
cat <<EOF
This is the custom-go-s2i S2I image:
To use it, install S2I: https://github.com/openshift/source-to-image
Sample invocation:
s2i build <source code path/URL> custom-go-s2i <application image>
You can then run the resulting image via:
docker run <application image>
EOF
Dockerfileを編集する。ベースイメージはRed Hat Container Catalogから取得するのが望ましいと思われるが、今回はDockerHubのものを使う。
FROM golang:1.12
LABEL maintainer="Your Name <your@email.com>"
LABEL io.k8s.description="A Go S2I builder image" \
io.k8s.display-name="Go S2I builder image" \
io.openshift.expose-services="8080:http" \
io.openshift.s2i.scripts-ulr="image:///usr/libexec/s2i" \
io.openshift.tags="builder, go, golang"
ENV APP_ROOT /opt/app-root
COPY ./s2i/bin/ /usr/libexec/s2i
RUN mkdir -p ${APP_ROOT} && \
chown -R 1001:1001 ${APP_ROOT} && \
chgrp -R 0 ${APP_ROOT} && \
chmod -R g=u ${APP_ROOT}
USER 1001
EXPOSE 8080
WORKDIR ${APP_ROOT}}
CMD ["/usr/libexec/s2i/usage"]
ビルドする。
cd custom-go-s2i
docker build -t custom-go-s2i:1.12 .
$ docker build -t custom-go-s2i:1.12 .
Sending build context to Docker daemon 22.53kB
Step 1/10 : FROM golang:1.12
---> 80bb9c6de3f2
Step 2/10 : LABEL maintainer="Your Name <your@email.com>"
---> Using cache
---> 613e6931e678
Step 3/10 : LABEL io.k8s.description="A Go S2I builder image" io.k8s.display-name="Go S2I builder image" io.openshift.expose-services="8080:http" io.openshift.s2i.scripts-url="image:///usr/libexec/s2i" io.openshift.tags="builder, go, golang"
---> Using cache
---> 5abe1287a367
Step 4/10 : ENV APP_ROOT /opt/app-root
---> Using cache
---> 03d0dac2e9d6
Step 5/10 : COPY ./s2i/bin/ /usr/libexec/s2i
---> Using cache
---> 4d0267aa8319
Step 6/10 : RUN mkdir -p ${APP_ROOT} && chown -R 1001:1001 ${APP_ROOT} && chgrp -R 0 ${APP_ROOT} && chmod -R g=u ${APP_ROOT}
---> Using cache
---> 21c9c19cb0ad
Step 7/10 : USER 1001
---> Using cache
---> 3364c5ab36b3
Step 8/10 : EXPOSE 8080
---> Using cache
---> c07ab7cf6395
Step 9/10 : WORKDIR ${APP_ROOT}
---> Using cache
---> 8fe5f15618e5
Step 10/10 : CMD ["/usr/libexec/s2i/usage"]
---> Using cache
---> e41359221ed9
Successfully built e41359221ed9
Successfully tagged custom-go-s2i:1.12
$
$ docker images custom-go-s2i
REPOSITORY TAG IMAGE ID CREATED SIZE
custom-go-s2i 1.12 e41359221ed9 4 minutes ago 814MB
$
ビルダーイメージの動作確認
GoのWebサーバーのコードを書く。
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
ローカルでビルダーイメージとコードを統合してイメージを作成してみる。
s2i build test/test-app/ custom-go-s2i:1.12 custom-go-app
$ s2i build test/test-app/ custom-go-s2i:1.12 custom-go-app
---> Installing application source...
---> Building application from source...
Build completed successfully
$
作成されたイメージを確認。
$ docker images custom-go-app
REPOSITORY TAG IMAGE ID CREATED SIZE
custom-go-app latest ef6d1ee144fd 9 seconds ago 821MB
$
ローカルで実行してアクセス確認。OpenShiftでは適当なUIDが割り振られて実行されるため、適当なUIDで実行する。
$ docker run --rm -it -d --name go-test -u 1234 -p 8080:8080 custom-go-app
4370e075cdd1b448f0b23afb6b2436e5ca396db521aa59d9fcbb9904d6481cce
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4370e075cdd1 custom-go-app "/usr/libexec/s2i/run" 8 seconds ago Up 7 seconds 0.0.0.0:8080->8080/tcp go-test
$ curl http://localhost:8080
Hello World
$
Minishiftへの登録
Minishiftのoc
コマンドへパスを通す。
eval $(minishift oc-env)
developer
でログインしていることを確認。ログインしていなければログイン。
oc whoami
oc login -u developer
プロジェクトを作成。
oc new-project custom-go
Minishiftでは内部レジストリーが公開されていないが、その場合にイメージを登録する方法は以下の記事が分かりやすい。Minishift内部のDockerエンジンからなら内部レジストリーに接続できる。
一旦イメージをファイルに保存する。
docker save custom-go-s2i:1.12 -o custom-go-s2i.tar
docker
コマンドの向き先をMinishift内のDockerエンジンに向ける。
eval $(minishift docker-env)
ファイルに保存しておいたイメージをロード。
docker load -i custom-go-s2i.tar
タグ付けしてMinishiftの内部レジストリーにプッシュ。
docker tag custom-go-s2i:1.12 $(minishift openshift registry)/custom-go/custom-go-s2i:1.12
docker login -u $(oc whoami) -p $(oc whoami -t) $(minishift openshift registry)
docker push $(minishift openshift registry)/custom-go/custom-go-s2i:1.12
ImageStreamが登録されたことを確認する。
$ oc get is
NAME DOCKER REPO TAGS UPDATED
custom-go-s2i 172.30.1.1:5000/custom-go/custom-go-s2i 1.12 18 seconds ago
$
docker
コマンドの向き先を戻しておく。
unset DOCKER_TLS_VERIFY
unset DOCKER_HOST
unset DOCKER_CERT_PATH
S2Iでのアプリのデプロイ
GoのWebアプリのソースコードのGitHubリポジトリーを作成する。
アプリをデプロイ。
oc new-app --name=hello custom-go-s2i:1.12~https://github.com/sotoiwa/go-sample
$ oc new-app --name=hello custom-go-s2i:1.12~https://github.com/sotoiwa/go-sample
--> Found image e413592 (About an hour old) in image stream "custom-go/custom-go-s2i" under tag "1.12" for "custom-go-s2i:1.12"
Go S2I builder image
--------------------
A Go S2I builder image
Tags: builder, go, golang
* A source build using source code from https://github.com/sotoiwa/go-sample will be created
* The resulting image will be pushed to image stream tag "hello:latest"
* Use 'start-build' to trigger a new build
* This image will be deployed in deployment config "hello"
* Port 8080/tcp will be load balanced by service "hello"
* Other containers can access this service through the hostname "hello"
--> Creating resources ...
imagestream.image.openshift.io "hello" created
buildconfig.build.openshift.io "hello" created
deploymentconfig.apps.openshift.io "hello" created
service "hello" created
--> Success
Build scheduled, use 'oc logs -f bc/hello' to track its progress.
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose svc/hello'
Run 'oc status' to view your app.
$
アプリが動き出したことを確認。
$ oc get po
NAME READY STATUS RESTARTS AGE
hello-1-build 0/1 Completed 0 1m
hello-1-xfkzb 1/1 Running 0 56s
$
アプリを外部公開。
oc expose svc hello --hostname hello.example.com
アクセス確認。
curl -H "Host: hello.example.com" http://$(minishift ip)
$ curl -H "Host: hello.example.com" http://$(minishift ip)
Hello World!!
$