- 投稿日:2019-07-24T23:38:06+09:00
terraformの公式イメージをgitlab-ciで使うときの注意点
terraformの公式イメージをgitlab-ciで使うときの注意点
はじめに
terraformの公式イメージを使って、gitlab-ciを実行するときに地味にハマったので注意点書く
使用した
.gitlab-ci.yml.gitlab-ci.yml(修正前)image: name: hashicorp/terraform:latest stages: - terraform_validate - terraform_plan - terraform_apply before_script: - terraform init --upgrade validate: stage: terraform_validate script: - terraform --version - terraform validate plan: stage: terraform_plan script: - terraform plan --parallelism=30 -out "planfile" artifacts: paths: - ./planfile apply: stage: terraform_apply script: - terraform apply -input=false "planfile" dependencies: - plan when: manualこれを実行した結果
Terraform Commands(CLI)にあるような、
terraformコマンドを実行した結果が出てる。In erroneous cases, a non-zero exit status will be returned.
と書いてあるように、0以外のstatusが返ってきてるため、エラーとなって終了している。
Usage: terraform [-version] [-help] <command> [args] The available commands for execution are listed below. The most common, useful commands are shown first, followed by less common or more advanced commands. If you're just getting started with Terraform, stick with the common commands. For the other commands, please read the help and docs before usage. Common commands: apply Builds or changes infrastructure console Interactive console for Terraform interpolations destroy Destroy Terraform-managed infrastructure env Workspace management fmt Rewrites config files to canonical format get Download and install modules for the configuration graph Create a visual graph of Terraform resources import Import existing infrastructure into Terraform init Initialize a Terraform working directory output Read an output from a state file plan Generate and show an execution plan providers Prints a tree of the providers used in the configuration refresh Update local state file against real resources show Inspect Terraform state or plan taint Manually mark a resource for recreation untaint Manually unmark a resource as tainted validate Validates the Terraform files version Prints the Terraform version workspace Workspace management All other commands: 0.12upgrade Rewrites pre-0.12 module source code for v0.12 debug Debug output management (experimental) force-unlock Manually unlock the terraform state push Obsolete command for Terraform Enterprise legacy (v1) state Advanced state management Usage: terraform [-version] [-help] <command> [args] The available commands for execution are listed below. The most common, useful commands are shown first, followed by less common or more advanced commands. If you're just getting started with Terraform, stick with the common commands. For the other commands, please read the help and docs before usage. Common commands: apply Builds or changes infrastructure console Interactive console for Terraform interpolations destroy Destroy Terraform-managed infrastructure env Workspace management fmt Rewrites config files to canonical format get Download and install modules for the configuration graph Create a visual graph of Terraform resources import Import existing infrastructure into Terraform init Initialize a Terraform working directory output Read an output from a state file plan Generate and show an execution plan providers Prints a tree of the providers used in the configuration refresh Update local state file against real resources show Inspect Terraform state or plan taint Manually mark a resource for recreation untaint Manually unmark a resource as tainted validate Validates the Terraform files version Prints the Terraform version workspace Workspace management All other commands: 0.12upgrade Rewrites pre-0.12 module source code for v0.12 debug Debug output management (experimental) force-unlock Manually unlock the terraform state push Obsolete command for Terraform Enterprise legacy (v1) state Advanced state management ERROR: Job failed: exit code 127理由
dockerhubのdockerfileをよく見ろということだ。
https://hub.docker.com/r/hashicorp/terraform/dockerfile
下記にあるように、
ENTRYPOINT ["terraform"]となっている。
そりゃ、terraformコマンドを実行するわけだ。FROM golang:alpine MAINTAINER "HashiCorp Terraform Team <terraform@hashicorp.com>" ENV TERRAFORM_VERSION=0.10.0 RUN apk add --update git bash openssh ENV TF_DEV=true ENV TF_RELEASE=true WORKDIR $GOPATH/src/github.com/hashicorp/terraform RUN git clone https://github.com/hashicorp/terraform.git ./ && \ git checkout v${TERRAFORM_VERSION} && \ /bin/bash scripts/build.sh WORKDIR $GOPATH ENTRYPOINT ["terraform"]結果
何でもいいから、
entrypointを取り敢えず上書きするようにしておく。.gitlab-ci.yml(修正後)image: name: hashicorp/terraform:latest entrypoint: - '' stages: - terraform_validate - terraform_plan - terraform_apply before_script: - terraform init --upgrade validate: stage: terraform_validate script: - terraform --version - terraform validate plan: stage: terraform_plan script: - terraform plan --parallelism=30 -out "planfile" artifacts: paths: - ./planfile apply: stage: terraform_apply script: - terraform apply -input=false "planfile" dependencies: - plan when: manual
- 投稿日:2019-07-24T21:56:14+09:00
既存のRuby on RailsプロジェクトにJenkins と Docker で CIを導入する
要約
引き継いだプロジェクトなどで既存のRailsアプリにCIがない場合に、気軽にテストを書いてCIを回す文化を醸成したいと思って対応した内容の記録です。
対象読者
Railsのプロジェクトを運用している方で、引き継いだプロジェクトなど何からの事情によりテストを書く環境がない、または、CI環境を構築したいが、日本語の情報が少ない(自分がそうでした)ために構築に苦労している方に向けた記事です。
構成
構築手順
1. ビルドマシンの準備
- 適当なLinuxマシンを用意してください。
- 今回の例ではCentos7を使用しています。
2. dockerインストール
- 公式の記述に従い最新版のインストールします。
- https://docs.docker.com/install/linux/docker-ce/centos/
3. docker-composeインストール
- こちらも公式より最新版のインストールを行います。
- https://docs.docker.com/compose/install/
4. Jenkins(スタンドアロン版)のインストール
- Jenkinsもdockerに閉じ込めたかったのですが、コンテナ上でdocker-compose の使用がうまく動かなかったため、今回はやむなくJenkinsだけは ビルドマシン上にwar配置という形をとりました。
# Jenkinsの起動スクリプト作成 $ mkdir ~/myjkdir $ cd myjkdir $ wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war . $ cat <<EOT> start_jk.sh JENKINS_JAVA_OPTIONS="-Xmx2048m -XX:MaxPermSize=512m -Dorg.jenkinsci.plugins.durabletask.BourneShellScript.LAUNCH_DIAGNOSTICS=true" nohup java -jar jenkins.war & EOT $ chmod +x start_jk.sh $ chown $USER:$USER start_jk.sh5. Railsにビルド用の各種設定を行う
- railsアプリをdockerにのせるための手順はこちらの通りで動作しました。
- https://docs.docker.com/compose/rails/
- ※ 後述していますが、この際、採用するイメージのミドルウェアのバージョンは実際に使用しているものに合わせるようにしましょう。コピペで進むとビルド出来ないなど後々不安定な挙動に悩むことになります。
6. ビルドマシンでdocker-composeのイメージビルド
# 適当なディレクトリに上記リポジトリをチェックアウトして、dockerイメージのビルド cd /myapp_dir # Checkout from SCM . docker-compose build docker images # エラーなく、イメージがビルドできていることの確認 docker-compose up # コンテナ起動確認 docker-compose run web bundle exec rake db:create7. Jenkinsファイルの用意
pipeline { agent any stages { stage('build') { steps { sh 'echo "Hello World"' } } stage('test') { steps { sh 'docker-compose run web bundle exec rake db:create' sh 'docker-compose run web bundle exec rake db:schema:load' sh 'docker-compose run web bundle exec rake test test/**/*.rb' } } } }
- 参考: https://medium.com/capital-one-tech/super-powering-your-enterprise-jenkins-ci-pipeline-with-docker-compose-a4f508598375
- Thank you https://medium.com/@dariendford !!
8. Jenkinsでビルドジョブ(pipeline)を作成し実行
- 無事ビルド完了。 これで、テストを書いていけば自動テストが回りデグレの防止などコード品質向上に 寄与してくれることでしょう。 私も安心して眠れます。(テストを書いてから寝ろ)
はまったポイント
以下では、上記CI環境構築の間にハマったポイントを記載します。
1. 既存アプリのミドルウェアバージョンを良く確認しましょう。
- レガシーなプロジェクトだと、使用しているソフトウェアのバージョンが古いこともあり、 公式等の記述コピペで進むとうまく動かない状況に陥ります。 docker imageに採用するタグ(バージョン)を良く確認しましょう。
※ 例えばruby2.3とpostgres9.4の組み合わせのシステムの場合
- Dockerfile
FROM ruby:2.3 ...
- docker-compose.yml
db: image: postgres:9.4 ...2. docker関連ファイルの改行コードはLFで統一
- Windowsでの作業で意図せずCRLFが混入すると、dockerがエラーを出力しますのでご注意ください。
- 私はこれで半日溶かしました。
- https://forums.docker.com/t/getting-panic-spanic-standard-init-linux-go-178-exec-user-process-caused-no-such-file-or-directory-red-while-running-the-docker-image/27318
- 特にDockerfileのEntrypointに指定するコードの改行コードが問題を引き起こすことが多いようです。
所感
テストが気軽にかける環境をローコストで手に入れることはソフトウェア品質向上に寄与すると思っています。Rails単体でも、かなり簡単にテストができる仕組みが入っていると思いますが、さらにDB回りやシステム全体のビルドテストとなると、Dockerみたいなアプリをパッケージにできる仕組みで手軽に作って捨てる環境を作りたいところですが、現状まだまだ設定が煩雑だったり日本語情報が少なかったりと、環境構築に障壁を感じました。少しでもこの記事が同じような境遇の方のお役に立てば幸いです。
- 投稿日:2019-07-24T20:20:46+09:00
docker 18.0.9.8 にアップデートがかかってdockerが使えなくなった。
現象
Ubuntu18.04でdocker-ceをインストールして使っていました。
以前は平気で使えていたdockerが急にdocker ps > Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?と言い出しました。
Qiitaのこの記事やいろんな記事を参考にしたのですが、解決しませんでした。
解決へ (ダウングレード)
そもそも何が起きたのか
/var/log/dpkg.logを見ると、数日前にdocker-ce:amd64 5:18.09.8~3-0~ubuntu-bionicにアップロードされたことがわかりました。
いろいろ調べても治らないので、
このgithubのissueを参考に、dockerのバージョンをダウングレードしました。
[Ubuntu] apt-get まとめを参考に、
sudo apt-cache policy docker-ceでインストール可能なdockerのバージョンが出てきます。
sudo apt install docker-ce=5:18.09.1~3-0~ubuntu-bionicとしてやってガイドに乗っていくと直りました。(Ubuntu 18.04 を使っているのでgithubのxenialをbionicに変えました。)
- 投稿日:2019-07-24T19:13:18+09:00
【k8s】Kubernetesやってみた【minikube】
kubernetesを触ってみたのでまとめてみました
目次
- 環境
- kubernetesについて
- minikube導入
- minikube起動
- ダッシュボードの起動
- サービスを作成してみる
- 後片付け
- 「Version string empty」エラーについて
- まとめ
環境
- MacBook Pro (Retina, 15-inch, Mid 2015)
kubernetesについて
kubernetesというのは「コンテナを運用しやすくするオープンソースなプラットフォーム」です。
最近よく耳にするkubernetesですが、色々な環境があるんですねー。よく耳にするものですと「minikube」でしょうか。
こちらは手元のローカル環境で動作させやすいkubernetesで、冗長性の担保はされてないですが動作が軽快だそうです。
minikubeのように手軽に試せる環境として「micro-k8s」、Iot(ラズパイなど)用のさらに軽量な「k3s」があります。クラウド上のKubernetesとして、「GKS(Googleさん)」、「ACS(Microsoftさん)」、「EKS(Amazonさん)」が提供されており、共通の特徴としてWebGUIでコンテナを管理できます。
Macユーザーだと「Docker for Mac」を利用している方が多いのではないでしょうか。
「Docker for Mac」では設定を行うことでkubernetes環境が利用できます。minikube導入
minikubeを利用してkubeってみましょう。過去に導入したものなので当時の導入手順は覚えてません。
がしかし、brew listコマンドで結果が返ってくるので恐らくbrewコマンドで導入したのだと思います。
うろ覚え申し訳ないです。$ brew list | grep kube kubernetes-cli $ brew cask list | grep kube minikube下記リンクの手順で導入できるかと思います。
minikube起動
VMにvirtualBoxを指定してminikube起動
$ minikube start --vm-driver=virtualbox $ minikube statusダッシュボードの起動
# 下記コマンドでダッシュボード起動(ブラウザが開きます) # minikubeのダッシュボードはターミナルで「Ctrl+c」で停止できます $ minikube dashboard$ kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.10 --port=8080「hello-minikube」を起動するコマンドを実行し、ブラウザにてダッシュボードのリロードを行うと「hello-minikube」のPodなどが追加されているのがわかりますね。
サービスを作成してみる
# 「hello-minikube」を外部アドレスから参照できるようにする $ kubectl expose deployment hello-minikube --type=NodePort## 各種情報を確認してみる(ダッシュボードと同じ情報が出力されます) $ kubectl get services $ kubectl get pod $ kubectl get deployments後片付け
ダッシュボードで作業しても良いですが、せっかくなのでコマンドでお掃除してみましょう。
# サービスの削除 $ kubectl delete services hello-minikube # デプロイの削除 $ kubectl delete deployment hello-minikube # minikubeの停止 $ minikube stop「Version string empty」エラーについて
minikube startした際にエラーが出ますが、issueを見た感じだと、バグのようです。
とりあえずは正常に動作するようなのでそのまま進めます。←エラー出るの気持ち悪いので詳しい方いましたらご指摘ください$ minikube start ~~中略~~ E0710 15:47:42.634326 85156 start.go:210] Error parsing version semver: Version string empty ~~中略~~ Everything looks great. Please enjoy minikube!まとめ
今回は触りの部分だけ実践しましたが、やはり学習コストが高い印象。。。Dockerは割と取っ付きやすかったが。。。
慣れて管理工数が減れば両手を挙げて喜べますが、本番運用への道のりは長くなりそうですw次回の記事ではymlファイルなどを定義して色々やってみようと思います。
- 投稿日:2019-07-24T18:57:57+09:00
【Java】プロジェクト新規作成から自動テスト/ビルド/デプロイ実現まで
TL;DR
git branchに変更が加わった際、自動で
- JUnit test (with MySQL)
- docker build
- Kubernetes環境にデプロイ
が行われるJavaプロジェクトを完全にゼロから構築します。
登場するもの
OSS
- Maven
- MySQL
- Docker
サービス
- GitHub
- CircleCI
- AWS (ECR, EKS) ⇦ 微修正でその他マネージドk8sにも応用可能かと思います。
サンプルプロジェクトの実装
最終的にディレクトリ構成はこんな感じになります。順を追って作っていきます。
GitHubからcloneして頂いても結構です。testproject/ ├ src/ │ ├ main/ │ │ └ java/ │ │ └testpackage/ │ │ └Main.java │ └ test/ │ └ java/ │ └testpackage/ │ └MainTest.java ├ .cifcleci/ │ └ config.yml ├ schema.sql ├ pom.xml ├ deploy.yaml └ Dockerfile1. スキーマ定義
テーブルスキーマを記述します。resourceフォルダに置いても良いのですが、今回はトップディレクトリに配置することにします。
データベース名は指定しません。schema.sqlCREATE TABLE user (id int, name varchar(10));2. mavenプロジェクト作成
先ほどのtableに適当なレコードを挿入する最小限のJavaプロジェクトを実装します。
JDBC、JUnit、maven-assembly-pluginを使用します。
pom.xml<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>aaaanwz</groupId> <artifactId>test</artifactId> <version>0.0.1</version> <name>testproject</name> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <!-- JDBC driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.17</version> </dependency> <!-- JUnit --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.3.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!-- JUnit test --> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M3</version> </plugin> <!-- Build runnable jar --> <plugin> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <archive> <manifest> <mainClass>testpackage.Main</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build> </project>1レコード挿入するだけのMainクラスを実装します。
データベースへの接続情報は環境変数から取得します。src/main/java/testpackage/Main.javapackage testpackage; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class Main { public static void main(String[] args) throws ClassNotFoundException, SQLException { final String host = System.getenv("DB_HOST"); final String dbname = System.getenv("DB_NAME"); execute(host, dbname); } static void execute(String host, String dbname) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection( "jdbc:mySql://" + host + "/" + dbname + "?useSSL=false", "root", ""); PreparedStatement stmt = conn.prepareStatement("INSERT INTO user(id,name) VALUES(?, ?)"); stmt.setInt(1, 1); stmt.setString(2, "Yamada"); stmt.executeUpdate(); } }レコードが挿入された事を確認するだけのテストを書きます。
src/test/java/testpackage/MainTest.javapackage testpackage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import testpackage.Main; class MainTest { Statement stmt; @BeforeEach void before() throws ClassNotFoundException, SQLException { Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mySql://localhost/test?useSSL=false", "root", ""); stmt = conn.createStatement(); } @AfterEach void after() throws SQLException { stmt.executeUpdate("TRUNCATE TABLE user"); } @Test void test() throws Exception { Main.execute("localhost", "test"); try (ResultSet rs = stmt.executeQuery("SELECT * FROM user WHERE id = 1;")) { if (rs.next()) { assertEquals("Yamada", rs.getString("name")); } else { fail(); } } } }3. Dockerfile作成
Dockerfileを書きます。テストは
docker buildとは別のステップで行う予定のため、-DskipTestsを付与してビルド時のテストをスキップします。イメージサイズ削減のためmaven:3.6でビルド、openjdk11:apline-slimで実行するマルチステージビルドを行います。
maven:3.6では約800MB、openjdk11:alpine-slimでは約300MBとなります。現時点でECRの無料枠は500MBのため、個人開発では大きな差です。DockerfileFROM maven:3.6 AS build ADD . /var/tmp/testproject/ WORKDIR /var/tmp/testproject/ RUN mvn -DskipTests package FROM adoptopenjdk/openjdk11:alpine-slim COPY --from=build /var/tmp/testproject/target/test-0.0.1-jar-with-dependencies.jar /usr/local/ CMD java -jar /usr/local/test-0.0.1-jar-with-dependencies.jar.jar4. k8s yamlファイル作成
3.でビルドされたコンテナをk8sにデプロイするためのyamlを書きます。今回のプログラムは単発でSQLを実行して終了するため、
kind: Jobにしてみます。Docker registryのurlは適宜置換してください。
envでDBへの接続情報を定義します。DB_HOSTの値がmysqlとなっているのは、KubernetesのService経由で接続するためです。k8s-job.yamlapiVersion: batch/v1 kind: Job metadata: name: test spec: template: spec: containers: - name: test image: your-docker-registry-url/testimage:latest imagePullPolicy: Always env: - name: DB_HOST value: "mysql" - name: DB_NAME value: "ekstest" restartPolicy: Never backoffLimit: 05. circleci configファイル作成
本稿のキモです。CircleCIで自動テスト/ビルドを行うための構成設定を書きます。
.circleci/config.ymlversion: 2.1 orbs: aws-ecr: circleci/aws-ecr@6.1.0 aws-eks: circleci/aws-eks@0.2.1 kubernetes: circleci/kubernetes@0.3.0 jobs: test: # ①JUnit テストの実行 docker: - image: circleci/openjdk:11 - image: circleci/mysql:5.7 environment: MYSQL_ALLOW_EMPTY_PASSWORD: yes MYSQL_DATABASE: test command: [--character-set-server=utf8, --collation-server=utf8_general_ci, --default-storage-engine=innodb] steps: - checkout - run: name: Waiting for MySQL to be ready command: dockerize -wait tcp://localhost:3306 -timeout 1m - run: name: Install MySQL CLI; Create table; command: sudo apt-get install default-mysql-client && mysql -h 127.0.0.1 -uroot test < schema.sql - restore_cache: key: circleci-test-{{ checksum "pom.xml" }} - run: mvn dependency:go-offline - save_cache: paths: - ~/.m2 key: circleci-test-{{ checksum "pom.xml" }} - run: mvn test - store_test_results: path: target/surefire-reports deploy: # ③EKSへのkubectl apply executor: aws-eks/python3 steps: - checkout - kubernetes/install - aws-eks/update-kubeconfig-with-authenticator: cluster-name: test-cluster aws-region: "${AWS_REGION}" - run: command: | kubectl apply -f k8s-job.yaml name: apply workflows: test-and-deploy: jobs: - test: # ①JUnit テストの実行 filters: branches: only: develop - aws-ecr/build-and-push-image: # ②コンテナのビルドとECRへのpush filters: branches: only: master create-repo: true repo: "testimage" tag: "latest" - deploy: # ③EKSへのkubectl apply requires: - aws-ecr/build-and-push-image①JUnitテストの実行
filterによって、
developブランチに変更が加わった際にmvn testが実行されるようにしてみました。この際テスト用MySQLインスタンスが立ち上がり、testデータベースが準備されます。公式ドキュメントで詳しく解説されています。
- Language Guide: Java
- Database Configuration Examples②コンテナのビルドとECRへのpush
masterブランチに変更が加わった際に、Dockerfileに従ってbuildし、ECRにpushします。
Orbクイックスタートガイドで詳しく解説されています。③EKSへのkubectl apply
②が実施された後、4.で定義したJobを実行します。
circleci/aws-eksに解説がありますが、サンプルコードをよりシンプルに変更しました。
@0.2.1のドキュメントによるとパラメータaws-regionはRequiredとなっていませんが、実際は必須のようです。ECRのpushで環境変数AWS_REGIONを要求されているので、これをそのまま使いました。インフラ設定
ほとんど公式ドキュメントへのリンク集です。
1. ECR, EKS環境準備
1-1. 基本設定
test-clusterを立ち上げます。
- Getting Started with Amazon EKS
- Setting Up with Amazon ECR1-2. EKS上にMySQLをデプロイ
Kubernetes公式にDeploy MySQLというドキュメントが用意されています。
kubectl exec -it mysql-0 mysqlコマンドからekstestデータベースとuserテーブルを用意します。2. CircleCI projectの設定
2-1. プロジェクトのセットアップ
2-2. 環境変数の設定
- circleci/aws-ecrでRequiredとなっている環境変数をCircleCI Projectに設定します。
Roleに要求される権限の詳細は割愛します。まとめ
- develop branchにpush
mvn testが実行され、テストレポートがCircleCIのTest summaryに表示されます。- master branchにpush
ECRにdocker imageがpushされ、EKSでJobが開始します。EKS上のMySQLにid:1 name:Yamadaレコードが挿入されます。いかがでしたでしょうか。テストをわざと落とす等色々試してみて頂ければと思います。
- 投稿日:2019-07-24T18:04:06+09:00
AmazonLinux2のdockerイメージにpythonをインストールしてAWS ECRにアップする方法
AWS環境を利用している環境において、CodePipeline/CodeBuild/CodeDeploy/CodeCommitを使用している方々、多くいらっしゃると思いますが、CodeBuildで使用するDockerイメージをどこで管理するかという課題に関して記述していければと思います。
Docker-hubで管理してもいいけどAWSで一元管理したい、Docker hub側のサイトでトラブルが起きてアクセスできなくなるのは困る、Docker hubのアカウントを取得して管理するのが面倒などあるかと思いましたので、データ分析基盤のDevOpsの一環で実施した内容を記述します。
環境及び前提
実行環境
VirtualBox (VM)
OS:AmazonLinux2
docker:18.06.1-ce
pyenv:1.2.13
Python:3.6.5VirtualBoxでAmazonLinux2のboxを作成し、amazon-linux-extrasでdockerをインストールして実施しています。
ECRのリージョンは東京リージョンで実施しています。最終ゴール
CI/CDでCodeBuildを使用する際の、AWSECR内でdockerイメージの管理Dockerイメージ作成準備
Dockerファイルで設定を記述した後、pythonのパッケージをインストールするための準備をします。
Dockerファイルの作成
Dockerファイル内では必要なパッケージのインストールおよび、pyenvのダウンロード、pythonのインストール、環境変数の設定を実施しています。
今回作成するイメージの基となるイメージはdockerhubのオフィシャルイメージから持ってきています。
https://hub.docker.com/_/amazonlinux以下がDockerファイルの中身
DockerFileFROM amazonlinux:2 ADD . . SHELL ["/bin/bash", "-c"] RUN yum update -y RUN yum install -y gcc bzip2 bzip2-devel openssl openssl-devel readline readline-devel git wget gcc-c++ unixODBC-devel tar.x86_64 RUN echo 'export PYENV_ROOT="/usr/local/pyenv"' | tee -a /etc/profile.d/pyenv.sh RUN echo 'export PATH="${PYENV_ROOT}/shims:${PYENV_ROOT}/bin:${PATH}"' | tee -a /etc/profile.d/pyenv.sh RUN echo 'eval "$(pyenv init -)"' | tee -a /etc/profile.d/pyenv.sh RUN git clone https://github.com/pyenv/pyenv.git /usr/local/pyenv RUN source /etc/profile.d/pyenv.sh && pyenv install -v 3.6.5 && pyenv global 3.6.5 && pip install --upgrade pip==19.0.3 && pip install -r requirements.txt && pip install awscli今回の環境はsshでログインするユーザにかかわらずデフォルトのpython2.7系ではなく、python3.6.5を利用できるようにprofile.dのpyenv.shでパスを管理しています。
requirements.txtの作成
pipでインストールしたいパッケージとそのバージョンを記載します。
既存の環境があるなら以下のコマンドを実行しインストールするパッケージの一覧を取得してください。pip freeze > requirements.txt既存の環境がない場合は、自作してください。
AWS ECRの設定
AWSコンソール上でECRにdockerイメージをpushできる環境を構築します。
リポジトリの作成
AWSコンソール画面にログインし、ECRサービスに遷移します。
そしてリポジトリを作成します。
今回はリポジトリ名を「python3.6.5」としています。IAMでECRへの適切な権限が与えられているユーザを用いる必要があります。
ECRのPermissionsの設定
以下はイメージをダウンロードする際に必要な設定です。
Permissions画面へ遷移し、以下のアカウントIDの部分を編集してJsonを貼り付けます。{ "Version": "2012-10-17", "Statement": [ { "Sid": "CodeBuildAccess", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::アカウントID:root" }, "Action": [ "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer" ] } ] }ECRへのイメージpush
ECRにログインし、dockerイメージをbuild後、実際にpushします。
以下アカウントID部分を修正して利用してください。$(aws ecr get-login --no-include-email) docker build -t アカウントID.dkr.ecr.ap-northeast-1.amazonaws.com/python3.6.5:latest . docker push アカウントID.dkr.ecr.ap-northeast-1.amazonaws.com/python3.6.5:latest注意点
- dockerにログインする必要はありません。
- コマンドを使用するOSにAWS CLIをインストールしている必要があります。
aws configureに指定しているaccesskeyに紐づくユーザは、ECRの利用をIAMで許可されている必要があります。- dockerにpushできない場合はセッションが切れている場合があるので、もう一度
$(aws ecr get-login --no-include-email)を実行する必要があります。まとめ
ECRで管理すればセキュリティも担保できる上に、CodeBuildからイメージをダウンロードする際の可用性が上昇するという印象でした。
特に難しいこともないので、是非試してみてください。
- 投稿日:2019-07-24T17:36:25+09:00
Vagrant環境のDockerで、Zabbixサーバとエージェントを構築する
イントロ
以前自分のWikiに「Vagrant環境のDockerサーバに、Zabbixのサーバとエージェントを構築する」って記事を書いたのですが、そのときはVagrantのProvision機能でDockerをチマチマ実行してました。
今回は同じ環境を docker-compose で作成します。
作成する環境
- 1つのVagrantfileで Zabbixサーバを1つ、別のVagrantfileで、監視されるエージェント側のOSを二つ構築します。
- ZabbixサーバはUbuntu Linux 上のDocker上に構築します。
- エージェント側もUbuntu Linuxとします。
- それぞれの仮想マシンはネットワーク的に到達可能である必要がありますが、Vagrantはデフォルトではおなじネットワークを共有しないようなので1、ウラLANとして 192.168.33.0/24 のネットワークを構築します。
- Zabbixサーバは80番ポートでWEBサーバが起動しますが、VagrantはNATかけないとアクセス出来ないので、port forwardingで 8888番ポートアクセスを80番ポートへ転送します。
ちなみに今回作業する環境は下記の通り。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.5 BuildVersion: 18F132 $Zabbixのバージョンは、日本語化の手順がエラーになる場合があるようで、 ubuntu-4.0.7 を指定しています。
コードの取得
使用するファイル群をGitHubから取得します。
$ git clone https://github.com/masatomix/environment_template.git $ cd environment_template/ $ git checkout -t origin/feature/for_qiita_zabbixZabbixサーバの構築
サーバの構築はVagrantで一発です。
$ vagrant upと実行することで、Ubuntu Linuxの構築から Dockerのインストール、Dockerサーバ上でのZabbixサーバのインストール、そのサーバ自体を監視するためのZabbixエージェントのコンテナのインストール、と設定と起動、までが行われます。
Vagrantが動いてるOS上のブラウザから
http://127.0.0.1:8888/へアクセスして、Zabbixサーバのログイン画面が表示されればOKです。admin/zabbix で入れることを確認しておきましょう。
ちなみにVagrantfile などはこんな
cloneした内容を見ればイイのですが、抜粋。
Vagrantfile# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "ubuntu/xenial64" config.vm.network "forwarded_port", guest: 80, host: 8888 config.vm.network "private_network", ip: "192.168.33.10" # コレを行わないと # http://www.masatom.in/pukiwiki/Vagrant/TIPS%BD%B8/#ab1dd863 # vagrant packageでexportしたBoxが正しく動かないため記述 config.vm.provider "virtualbox" do |vb| vb.customize [ "modifyvm", :id, "--uartmode1", "disconnected", "--memory", 4096 ] end config.vm.provision :shell, :path => "./script/provision_init.sh",:privileged => false config.vm.provision :shell, :path => "./script/provision_ja.sh",:privileged => false config.vm.provision :shell, :path => "./script/provision_docker.sh",:privileged => false config.vm.provision :shell, :path => "./script/provision_docker_zabbix.sh",:privileged => false endprovision_docker_zabbix.sh#!/bin/sh cd /vagrant/zabbix sudo docker-compose up -d --builddocker-compose.yml はこちら
Docker上にZabbixサーバを構築するときにうごいた docker-compose.yml はこちらです。
docker-compose.ymlversion: '3.5' services: mysql-server: image: mysql:5.7 command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci'] environment: - MYSQL_DATABASE=${DB_DATABASE} - MYSQL_USER=${DB_USER} - MYSQL_PASSWORD=${DB_PASSWORD} - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} volumes: - /etc/localtime:/etc/localtime:ro - ./db/mysql_data:/var/lib/mysql user: "1000:50" # remove at Photon restart: always zabbix-java-gateway: image: zabbix/zabbix-java-gateway:${VERSION} volumes: - /etc/localtime:/etc/localtime:ro restart: always zabbix-server-mysql: image: zabbix/zabbix-server-mysql:${VERSION} depends_on: - mysql-server - zabbix-java-gateway environment: - DB_SERVER_HOST=mysql-server - MYSQL_DATABASE=${DB_DATABASE} - MYSQL_USER=${DB_USER} - MYSQL_PASSWORD=${DB_PASSWORD} - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} volumes: - /etc/localtime:/etc/localtime:ro ports: - 10051:10051 restart: always zabbix-web-nginx-mysql: build: ./nginx/ depends_on: - mysql-server - zabbix-server-mysql - zabbix-java-gateway environment: - DB_SERVER_HOST=mysql-server - MYSQL_DATABASE=${DB_DATABASE} - MYSQL_USER=${DB_USER} - MYSQL_PASSWORD=${DB_PASSWORD} - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} - ZBX_SERVER_HOST=zabbix-server - PHP_TZ="Asia/Tokyo" volumes: - /etc/localtime:/etc/localtime:ro links: - zabbix-server-mysql:zabbix-server ports: - 80:80 restart: always zabbix-agent: image: zabbix/zabbix-agent:${VERSION} links: - zabbix-server-mysql:zabbix-server volumes: - /etc/localtime:/etc/localtime:ro restart: always.envVERSION=ubuntu-4.0.7 DB_DATABASE=zabbix DB_USER=zabbix DB_PASSWORD=zabbix DB_ROOT_PASSWORD=zabbix構築している内容は 以前記事にした モノとほとんど同じなので、細かい説明は省略します。
Zabbixエージェントの構築
つづいてエージェント側。
$ cd agent $ vagrant upと実行することで、Ubuntu Linuxの構築から Zabbixエージェントのインストールと設定と起動、までが行われます。
vagrant upが完了したらOSが二つ立ち上がっているはずので、ログイン出来ることを確認しておきましょう。$ vagrant ssh agent001 (agent002) Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-139-generic x86_64) ... vagrant@agent001:~$ちなみにVagrantfile などはこんな
cloneした内容を見ればイイのですが、抜粋。
agent/Vagrantfile# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "ubuntu/xenial64" config.vm.define :agent001 do | agent001 | agent001.vm.hostname = "agent001" agent001.vm.network :private_network, ip: "192.168.33.11" agent001.vm.provision :shell, :path => "./script/provision.sh",:privileged => true end config.vm.define :agent002 do | agent002 | agent002.vm.hostname = "agent002" agent002.vm.network :private_network, ip: "192.168.33.12" agent002.vm.provision :shell, :path => "./script/provision.sh",:privileged => true end endZabbix Server自体の監視開始
ブラウザからZabbixの環境設定をおこないます。
http://127.0.0.1:8888/ へアクセスし、admin/zabbix でログイン します。あ、まずは右上のヒトのアイコンをクリックして、LanguageをJapaneseにしておきます。
さて、まずはZabbix サーバ自体の監視を行います。
設定 >> ホスト >> Zabbix server で、DNS名に「zabbix-agent」と入力、接続方法を「DNS」へ変更し、更新をクリックします2。
上記の通り、ほどなくして「ZBX」のアイコンが緑になっていればOKです。
各OSのエージェントでの監視開始(自動登録)
続いて、各OS agent001/agent002 の監視設定を追加します。元の記事 では手動登録していますが、同じようにやってもおもしろくないので、今回はディスカバリ機能を用いた自動登録を行ってみます。
手順はこんな感じ。
- 設定 >> ディスカバリ の画面で、特定のローカルネット上の Zabbixエージェントを定期的に検索する設定を追加。そのときに、
system.unameの値を取得するようにしておく- 設定 >> アクション の画面で、さきの検索にヒットした エージェントのうち、登録したいエージェントをフィルタする設定を記述
- 設定 >> アクション >> 実行内容 で、ホストを追加したり、それをホストグループに入れたり、テンプレートをリンクしたりなど、実行したい処理を記述。
という流れになるようです。
ディスカバリルールの作成
名前に「My Local Network」、IPアドレスの範囲を今回設定した「192.168.33.1-20」くらいに設定、監視間隔を一旦60sに(たぶん有効なはず)。またチェックの欄の「新規」をクリック。
チェックのタイプを指定出来るので「Zabbixエージェント」を選択
キーに「
system.uname」を選択して、「追加」をクリックします。
追加されました。最後に全体の「追加」ボタンを押せば完了です。
監視データ >> ディスカバリ に遷移してみると、条件に合致したエージェント(192.168.33.11,12)が発見されていることが確認できるとおもいます。
ちなみに
system.unameって。途中ででてきた、チェックのキーとして設定した
system.unameについてですが、ここにはZabbixがエージェントから取得できるデータ名を指定することが出来るようで、たとえばsystem.unameは下記のコマンドの実行結果となります。(Server側のUbuntuで)vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose exec zabbix-server-mysql zabbix_get -s zabbix-agent -k system.uname Linux fdd3e6a15327 4.4.0-139-generic #165-Ubuntu SMP Wed Oct 24 10:58:50 UTC 2018 x86_64 vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose exec zabbix-server-mysql zabbix_get -s 192.168.33.11 -k system.uname Linux agent001 4.4.0-139-generic #165-Ubuntu SMP Wed Oct 24 10:58:50 UTC 2018 x86_64 vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose exec zabbix-server-mysql zabbix_get -s 192.168.33.12 -k system.uname Linux agent002 4.4.0-139-generic #165-Ubuntu SMP Wed Oct 24 10:58:50 UTC 2018 x86_64 vagrant@ubuntu-xenial:/vagrant/zabbix$このあとのアクションの設定で「この戻り値(受信した値) に agent00 が含まれていたら」など条件を指定できます。なので、このあとで使用したい値を記載しておく、という感じになります。
アクションの定義
続いて、アクションを定義していきます。
設定 >> アクションに移動し、イベントソースを「ディスカバリ」にして、「アクションの作成」をクリック。
名前を「Auto discovery (Local Network)」、新規条件を「サービスのタイプ」にして、「Zabbixエージェント」を選択し、追加 をクリック。
実行条件が追加出来ました。実行条件は複数設定できるので、たとえば「受信した値」に「agent00」を含む3 なんて条件を追加してみましょう。
追加。
つづいて「実行内容」を選択します。実行内容は条件に合致するエージェントに対する処理のことで「ホストを追加」「ホストグループに追加」「テンプレートとのリンクを作成」などを実施します。
実行内容のタイプ は「ホストを追加」を選んで「追加」
追加されました。
また「新規」を選択し「ホストグループに追加」、ホストグループ名に「Discovered hosts」を設定し
「追加」をクリック。
追加されました。
また「新規」を選択し「テンプレートとのリンクを作成」、テンプレートに「linux」などと入れると「Template OS Linux」などと補完候補が出てくるのでそれを選択。
「追加」をクリックすると、、
追加されました。最後にボタンの「追加」をクリックすれば、、、
設定>>ホスト をしばらく見ていると、、、agent001(192.168.33.11),agent002(192.168.33.12)が追加されましたねー。。。
ちなみにアクションには他にも、「あのディスカバリルールで検知したエージェントのときだけ」なんて設定も可能です。
以上で、基本的なZabbixサーバ/Zabbixエージェントの環境構築は完了です。
今回はVagrantでコマンド一発で環境構築をしましたが、オンプレやAWSに構築する場合も基本的に同じコマンドを叩けばOKでしょう。おつかれさまでした。
おまけ。データのバックアップ
ついでに、MySQLのデータベースのバックアップ手順もまとめておきます。
vagrant sshでZabbix サーバにログイン後、
vagrant@ubuntu-xenial:~$ cd /vagrant/zabbix/に移動しておきます。
MySQL以外のコンテナの停止
vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------------------- zabbix_mysql-server_1_bbe6d5af81da docker-entrypoint.sh --cha ... Up 3306/tcp, 33060/tcp zabbix_zabbix-agent_1_e8a8079c2325 /sbin/tini -- docker-entry ... Up 10050/tcp zabbix_zabbix-java-gateway_1_92505d90c8f9 docker-entrypoint.sh Up 10052/tcp zabbix_zabbix-server-mysql_1_e37acaaa644d /sbin/tini -- docker-entry ... Up 0.0.0.0:10051->10051/tcp zabbix_zabbix-web-nginx-mysql_1_432a2d375844 docker-entrypoint.sh Up 443/tcp, 0.0.0.0:80->80/tcp vagrant@ubuntu-xenial:/vagrant/zabbix$起動しているコンテナを、docker-compose の機能で停止します。引数は
docker-compose.ymlに書いてある「サービス名」もしくは上記のNameの一部分を使用します。vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose stop zabbix-agent zabbix-java-gateway zabbix-server-mysql zabbix-web-nginx-mysql Stopping zabbix_zabbix-web-nginx-mysql_1_432a2d375844 ... done Stopping zabbix_zabbix-agent_1_e8a8079c2325 ... done Stopping zabbix_zabbix-server-mysql_1_e37acaaa644d ... done Stopping zabbix_zabbix-java-gateway_1_92505d90c8f9 ... done vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------------------------- zabbix_mysql-server_1_bbe6d5af81da docker-entrypoint.sh --cha ... Up 3306/tcp, 33060/tcp zabbix_zabbix-agent_1_e8a8079c2325 /sbin/tini -- docker-entry ... Exit 0 zabbix_zabbix-java-gateway_1_92505d90c8f9 docker-entrypoint.sh Exit 143 zabbix_zabbix-server-mysql_1_e37acaaa644d /sbin/tini -- docker-entry ... Exit 0 zabbix_zabbix-web-nginx-mysql_1_432a2d375844 docker-entrypoint.sh Exit 0 vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d44071b826a6 mysql:5.7 "docker-entrypoint.s…" 16 minutes ago Up 16 minutes 3306/tcp, 33060/tcp zabbix_mysql-server_1_bbe6d5af81daMySQL以外が停止されました。
以後「MySQL以外のコンテナの停止」といったらこの作業を指すこととしましょう。データのバックアップ
MySQLコンテナに入って、データをバックアップします。
vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose exec mysql-server /bin/bash I have no name!@d44071b826a6:/$ mysqldump --single-transaction -uzabbix -pzabbix zabbix > /tmp/db20190722.dump mysqldump: [Warning] Using a password on the command line interface can be insecure. I have no name!@d44071b826a6:/$ exit exitコンテナ内の
/tmpにバックアップデータが出力されました。つづいてコンテナからこのデータを取り出します。
vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker cp d44071b826a6:/tmp/db20190722.dump ./ vagrant@ubuntu-xenial:/vagrant/zabbix$ ls -lrt 合計 2736 drwxr-xr-x 1 vagrant vagrant 96 7月 22 00:07 nginx drwxr-xr-x 1 vagrant vagrant 96 7月 22 00:07 db -rw-r--r-- 1 vagrant vagrant 2091 7月 22 00:07 docker-compose.yml -rw-r--r-- 1 vagrant vagrant 2796867 7月 22 00:35 db20190722.dump <- コレ vagrant@ubuntu-xenial:/vagrant/zabbix$コンテナからの取り出しが完了しました。dumpによるフルバックアップは、このデータを保管しておけばOKです。
最後に各サーバを起動して、バックアップは完了です。vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose start zabbix-agent zabbix-java-gateway zabbix-server-mysql zabbix-web-nginx-mysql Starting zabbix-java-gateway ... done Starting zabbix-server-mysql ... done Starting zabbix-web-nginx-mysql ... done Starting zabbix-agent ... done vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------------------- zabbix_mysql-server_1_bbe6d5af81da docker-entrypoint.sh --cha ... Up 3306/tcp, 33060/tcp zabbix_zabbix-agent_1_e8a8079c2325 /sbin/tini -- docker-entry ... Up 10050/tcp zabbix_zabbix-java-gateway_1_92505d90c8f9 docker-entrypoint.sh Up 10052/tcp zabbix_zabbix-server-mysql_1_e37acaaa644d /sbin/tini -- docker-entry ... Up 0.0.0.0:10051->10051/tcp zabbix_zabbix-web-nginx-mysql_1_432a2d375844 docker-entrypoint.sh Up 443/tcp, 0.0.0.0:80->80/tcp vagrant@ubuntu-xenial:/vagrant/zabbix$起動されました。以後「各サーバを起動」といったらこの作業を指すこととしましょう。
おまけ。データのリストア
コンテナ停止
既出の手順「MySQL以外のコンテナの停止」を実施します。
リストア準備
さてMySQL以外が停止している状態で、リストアを開始します。手順は、すでに存在するデータベースを削除したのち、事前に取得しておいたバックアップデータを戻すという流れです。
まずはMySQLコンテナにバックアップデータをコピーします。
vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker cp ./db20190722.dump d44071b826a6:/ vagrant@ubuntu-xenial:/vagrant/zabbix$ sudo docker-compose exec mysql-server /bin/bash I have no name!@d44071b826a6:/$ ls -lrt total 2800 ... -rw-r--r-- 1 1000 1000 2796867 Jul 22 00:35 db20190722.dump I have no name!@d44071b826a6:/$コンテナへデータを転送出来ました。
DB削除・空DB作成・リストア
I have no name!@d44071b826a6:/$ mysql -uzabbix -pzabbix ... Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> drop database zabbix; Query OK, 144 rows affected (1.70 sec) mysql> create database zabbix; Query OK, 1 row affected (0.01 sec) mysql> exit Byeさて、データを入れていきます。
I have no name!@d44071b826a6:/$ mysql -uzabbix -pzabbix zabbix < ./db20190722.dump mysql: [Warning] Using a password on the command line interface can be insecure. I have no name!@d44071b826a6:/$ I have no name!@d44071b826a6:/$ exit exitリストア完了です。
起動
最後に「各サーバを起動」しましょう。おつかれさまでした!
関連リンク
- 投稿日:2019-07-24T16:26:51+09:00
【2019年7月版】Hyperledger Indy のサンプル(ちょい古め)を動かしてみた
前回ビルドに挑戦したHyperledger Indyですが引き続き動作確認を行ってまいります。というか、ユースケースがいまいちピンと来ないので、懲りずに古いサンプルを動かしてみました。
紆余曲折ありましたがなんとか動いたので手順などの解説をいたします。
(めちゃくちゃ大変だった。)まず、修正済みのソースはこちらです。
手っ取り早く動かしたい方、DockerインストールしたUbuntuで上記リポジトリをcloneしてReadmeの手順に従っていただければOKです!以下では通常の動作手順について、順を追って解説します。
1. コンテナのビルド
まず、Rustでのindyソースをコンテナ内でビルドして、デモに必要な各種のコンテナを作成します。
こちらの修正済みのプロジェクト からソースをクローンしておきます。以下では、
~/indy-ssivc-tutorialにクローン済みとして説明いたします。また、docker コマンドは
sudo付きで動かす環境であるとして説明します。1-1. indy コンテナのビルド
以下のコマンドで、indy 本体のネットワークを構成する docker コンテナをビルドします。
$ cd ~/indy-ssivc-tutorial/von-network $ sudo ./manage build1-2. API コンテナのビルド
以下のコマンドで indy とアクセスする API や管理ツールなどのコンテナ群をビルドします。
$ cd ~/indy-ssivc-tutorial/TheOrgBook/docker $ sudo ./manage.sh build1-3. デモアプリコンテナのビルド
以下のコマンドで indy のデモを行う Web アプリ用のコンテナ群をビルドします。
$ cd ~/indy-ssivc-tutorial/permitify/docker $ sudo ./manage buildこのあたりになるとディスクスペースやメモリなど逼迫してくるかもしれません。不要な docker イメージは削除して軽くしておいたほうがいいかもしれません。
2. 起動
無事に docker コンテナがビルドできたら同様の順番でコンテナを起動していきます。
2-1. indy ネットワークの起動
以下のコマンドで indy のテストネットワークを起動します。
$ cd ~/indy-ssivc-tutorial/von-network $ sudo ./manage startこれでindy用のコンテナがいくつか起動します。
2-2. API コンテナ群の起動
続いて indy に直接接続する API 用のコンテナ群を起動します。
新しいコンソールを開き、$ cd ~/indy-ssivc-tutorial/TheOrgBook/docker $ sudo ./manage.sh startで、API用のコンテナがいくつか起動します。
2-2-1. 起動するサイト・サービス
この時点でいくつかのサイトが立ち上がります。
- ダッシュボード Web UI ・・・ http://localhost:9000
- チュートリアルサイト ・・・ http://localhost:8080
- Swagger ・・・ http://localhost:8081
- Solr ・・・ http://localhost:8983
- PostgreSQL・・・tcp://localhost:5432
Solrはまぁ、おまけみたいなものです。
2-3. デモアプリコンテナ群の起動
以下のコマンドでデモアプリ用のコンテナ群を起動します。
新しいコンソールを開き、$ cd ~/indy-ssivc-tutorial/permitify/docker $ sudo ./manage start all APPLICATION_URL=http://192.168.1.10 THE_ORG_BOOK_APP_URL=http://192.168.1.10:8080で、OKです。
ここで重要なのが、
APPLICATION_URLで渡しているのが、デモアプリ用のコンテナ群が立ち上がるホストのIPアドレス、THE_ORG_BOOK_APP_URLで渡しているのが、上記のAPI用コンテナ群が立ち上がるホストのアドレス(ポート番号込み)です。
今回は1台のDockerホスト上で全てのコンテナを動かすので同一のIPアドレスとなっています。
また、この変数を設定せずに単に./manage start allと実行した場合は、ローカルホストからのみのアクセス が有効になります。2-3-1. 起動するサイト・サービス
ここでデモ用のサイト群がわーっと立ち上がります。
- Gov ID ・・・ http://localhost:5000
- Fabor 大学 ・・・ http://localhost:5006
- Acme 就職 ・・・ http://localhost:5007
- Acme 給与受け取り ・・・ http://localhost:5008
- Thrift 銀行 ・・・ http://localhost:5009
上記の手順で
APPLICATION_URLを使用している場合は、localhostの代わりにそのIPアドレスでアクセス可能です。3. コンテナの停止
各コンソールで
Ctrl+Cでプロセスを落とせばGraceful Shutdownとなります。4. 使用済みの container と volume の削除
前回の記事でも注意として記載しましたが、indyはブロックチェーンのプロダクトでありますので一度、動かしてブロックが生成されてしまうと後戻りができません。
テストネットを止めて再起動、ということが簡単にできませんので、デモサイトを落とした後はこの削除の手順が必須です。4-1. indy 用コンテナの削除
以下のコマンドで削除を行います。
$ cd ~/indy-ssivc-tutorial/von-network $ sudo ./manage rm4-2. API用コンテナの削除
同様に以下のコマンドで使用済みコンテナの削除を行います。
$ cd ~/indy-ssivc-tutorial/TheOrgBook/docker $ sudo ./manage.sh rm4-3. デモサイト用コンテナの削除
同様に以下の手順で削除します。
$ cd ~/indy-ssivc-tutorial/permitify/docker $ sudo ./manage rm基本的な動作方法は以上です。
4-4. 動かし方
実際のデモサイトのアクセス方法などはこちらをご覧ください。
また、ここでどんなことを実現したいのか?については以下の記事でわかりやすく解説していただいてます。
これらのデモサイトでどんなことができるのか、できるようにしたいのか、はお分かりいただけたかと思います。
5. どうやって動かしたのか
ここからが一応の本題です。この
ちょい古めのサンプルは、最新の Rust ではコンパイルが通りません。
また、API用サーバーやデモサイトなどのコードが大量にあるため、libindy を最新のものにしてコンパイル通ればオK☆、なんてことにはなりません。
当時の AS IS で動作確認が必要なのであります。
そんなわけで今回の古めのサンプル(といっても一昨年だけど。。。)をちゃんと動作させるに当たって、どうやって手当てをしたか、について述べていきたいと思います。1. Rustのビルド
まず、もっとも困難だったのが
どのバージョンのRustならビルドが通るのか、そして同時に全体がよろしく収まってくれるかです。上記でも述べましたが各種パッケージを最新にすれば現状のRustでビルドが通るのは前回のトライで確認済みです。しかし、参照するコードが大量にあるためコア部分のみバージョンアップする、なんてことはとてもできないのです。というわけで、当時の libindy はどうやってビルドしていたの?をどうやって調べたか、ですが、まず cargo のパッケージを調べました。
以下が、例えばですが、indy 1.6.7 の登録情報です。
https://crates.io/crates/indy/1.6.7
当たり前ですがちゃんとビルドされてcargoに登録されています。・・・どうやって?
でも、単にビルドして、アップロードしてるわけじゃないよね・・・?
たぶん jenkins か circle-ci とかでUTは通してるはずでしょう・・・というわけで・・・https://github.com/hyperledger/indy-sdk/tree/master/libindy/ci
はい、libindy が ci でテストを実施している流れは
ubuntu.dockerfileに書いてあります。そしてlibindyをビルドするrustをインストールする箇所で・・・ubuntu.dockerfile... USER indy RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.36.0 ENV PATH /home/indy/.cargo/bin:$PATH ...はい、Rustのバージョン指定してますね!つまり、その当時の ubuntu.dockerfile を見ればいい というわけですね!
そして
当時とはいつなのか?というと・・・indy-ssivc-tutorial/von-network/Dockerfileに以下の記述があります。von-network/Dockerfile... RUN git clone https://github.com/hyperledger/indy-sdk.git WORKDIR /home/indy/indy-sdk/libindy RUN git fetch RUN git checkout 778a38d92234080bb77c6dd469a8ff298d9b7154 ...この
checkout 778a38d92234080bb77c6dd469a8ff298d9b7154のハッシュ値を github のURLに貼り付けるとコミットログを見ることができます。具体的には以下のURLで確認できます。https://github.com/hyperledger/indy-sdk/commit/778a38d92234080bb77c6dd469a8ff298d9b7154
6 Mar 2018のコミットであることが確認できます。この当時の ubuntu.dockerfile を見ればいいというわけですね!いや、大変だった!wというわけで
ubuntu.dockerfileのコミットログを確認してみましょう。https://github.com/hyperledger/indy-sdk/commits/master/libindy/ci/ubuntu.dockerfile
このリストから2018.03.06以前の最新版を探してくればOK、ということになります。
というわけで・・・この
26 Feb 2018のコミット近辺の rust のバージョンが分かればいいんですね~というわけで、ubuntu.dockerfileを見てみますと・・・... ENV RUST_ARCHIVE=rust-1.21.0-x86_64-unknown-linux-gnu.tar.gz ENV RUST_DOWNLOAD_URL=https://static.rust-lang.org/dist/$RUST_ARCHIVE ...上記の定義で
1.21.0をダウンロードしてますね。。。う~ん、tar.gz をそのままダウンロードしてるのはちょっとなぁ。。。と、次のコミットを確認します。ここでの
ubuntu.dockerfileを見てみますと・・・... RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.21.0 ...
rustupでバージョン指定する方法が書かれてますね!これっぽい!!いや、実際には
1.21.0ではダメで、次の "Apr 23, 2018" の "Update rust to 1.25.0." が微妙にダメ(ビルドは通ったけど、サイト動かすとダメ)で、次の "May 30, 2018" の "Increment Rust version to 1.26.0" でうまくいくようになりました。これで Rust のコンパイルエラーはなくなりました。
すでに3日ほど経過してます。2. 参照パッケージのバージョン
Dockerfile 内で
apt installでindy_plenumなどをインストールしてますが、リポジトリサイトの"deb https://repo.sovrin.org/deb xenial $indy_stream"からご指定のバージョンは既に削除されているのですね・・・というわけで現在登録されているバージョンの最古のものから順にちゃんとバージョン間の依存性の整合性がとれているものを割と総当たりで試してみました。とは言え、古いもの順ではうまくいく組み合わせはすぐ見つかりました。
結果、
indy_plenum_ver=1.2.242、indy_node_ver=1.2.301が適しているようです。3. tob-web のビルドが通らない
tob-web/package.jsonに以下のような参照があります。tob-web/package.json... "localize-router": "git+https://github.com/cywolf/localize-router.git", ...これは最新版ではコケます。当時の依存関係とは変わっているのですから当然です。
(っていうかリポジトリ直接はやめてw)
そして以下の issue を発見しました。https://github.com/IBM-Blockchain-Identity/indy-ssivc-tutorial/issues/26
やっぱりビルド通らないよね?と思っていたら・・・"バージョン
1.0.1に直したよ" というコメントがあったので、その通りにいたしました。あら不思議、ビルドが通っちゃう・・・
4. permitify のビルドが通らない。
このIndyのサンプルプログラムは permitify など Django ベースのWebサイトを多数、起動するのですが、Django の起動がうまくいったか失敗したかがぱっと見ではわからないので、ちょっとハマりました。
コンテナではうまくいっているように見えて、コンテナの中に入って psするとpyhton のプロセスもあるけど、ssコマンドで確認するとポートをlistenしていない。。。というわけで
manage.py startとかやってみると初めてエラーメッセージがダラーっと出てて来る、そんな状態でした。Pythonプロセスが無駄に生きてるからやっかいなんですよね~。とりあえず、エラーメッセージが出てくれればもう後はググって対応だけなのでなんとかなりました。
依存関係のバージョンを以下のように修正しただけです。
- attr : 17.3.0 -> 17.4.0
- von-agent: 0.5.0 -> 0.5.2
これだけで半日かかってますけど。5. localhost からしか動作しない
これはだいぶ困りました。実際の手順では http://localhost:8080 のチュートリアルサイトから http://localhsot:500x の各サイトへリンクが表示されています。
そしてそれがlocalhost決め打ちなんですね。。。いや、それはどうなのよ~?とソース(Angular) を見てみましたが、外のAPI(http://localhost:8081)から取得するだけで Angular側では全然、決めていない・・・オーマイ。。。となってしまったわけです。
いろいろ見てみると、docker-compose.ymlで以下のような記述があります。
permitify/docker/docker-compose.yml... TEMPLATE_NAME: faber_college THE_ORG_BOOK_API_URL: ${THE_ORG_BOOK_API_URL} THE_ORG_BOOK_APP_URL: ${THE_ORG_BOOK_APP_URL} APPLICATION_IP: 0.0.0.0 APPLICATION_PORT: 8080 APPLICATION_URL: ${APPLICATION_URL}:5006 ...これはなんか、
${APPLICATION_URL}は自分のサイトのアドレスで${THE_ORG_BOOK_APP_URL}は http://localhost:8080 に戻る時のURLなんじゃないの?っぽいよね??という勘と、manageスクリプトでpermitify/docker/manage... configureEnvironment () { for arg in $@; do case "$arg" in *=*) export ${arg} ;; esac done export APPLICATION_URL=${APPLICATION_URL-http://localhost} # export THE_ORG_BOOK_API_URL=${THE_ORG_BOOK_API_URL-https://django-devex-von-dev.pathfinder.gov.bc.ca/api/v1} # export THE_ORG_BOOK_APP_URL=${THE_ORG_BOOK_APP_URL-https://devex-von-dev.pathfinder.gov.bc.ca} export THE_ORG_BOOK_API_URL="http://$DOCKERHOST:8081/api/v1" export THE_ORG_BOOK_APP_URL="http://$DOCKERHOST:8080" export TOB_INDY_SEED=the_org_book_issuer_000000000000 export LEDGER_URL=http://von-web:8000 } ...ここで、'=' が含まれていたら
exportしているので変数渡せるようにしてくれているんだということと、APPLICATION_URL、THE_ORG_BOOK_APP_URLのアドレスがlocalhostとdockerのhostでlocalhostじゃないとダメな理由がはっきりしましたね。localhostは100歩譲って外から見たIPでも動くと思いますが、Docker hostは完全に docker が動いているホストのdockerネットワーク上のIPアドレスなのでそのマシンから見ないとこのアドレスは解決できないでしょう、ということですね。たぶん。そんなわけで
THE_ORG_BOOK_APP_URLはいきなり$DOCKERHOSTを使わずに、外からちゃんと指定できる余地を残しておけばよいのです。以下のように。permitify/docker/manage... export THE_ORG_BOOK_APP_URL=${THE_ORG_BOOK_APP_URL-http://$DOCKERHOST:8080} ...で、起動時に外から見えるIPアドレスを教えてあげればOKなわけです。きっと。
$ ./manage start all APPLICATION_URL=http://192.168.1.10 THE_ORG_BOOK_APP_URL=http://192.168.1.10:8080この指定がうまく動いたので、Indyデモサイトは外部から http://192.168.1.10:8080 でめでたくアクセスできるようになりました。
いったん、以上といたします。いや~長かった。。。
- 投稿日:2019-07-24T08:11:48+09:00
Raspbian GNU/Linux 10 BusterにDockerをインストールする
ref: https://github.com/docker/for-linux/issues/709
にissueが上がっている通りで2019/07/23時点ではRaspbian busterにdocker-ceはそのままではインストールできない。よって
curl -sSL https://get.docker.com/ | sed 's/"buster"/"stretch"/' | shとして、
busterとしてではなく、stretch用のをインストールすることで回避できる。workaroundなやり方なので正式対応が来たらアップデートしましょう。






























