- 投稿日:2020-10-25T21:52:09+09:00
【祝】強化学習ライブラリTF2RL v1.0到達 ~CIやドキュメントサイトなど開発・利用環境の整備~
1. はじめに
以前紹介した友人が開発しているTensorFlow 2.x 向け強化学習ライブラリTF2RLが、諸々整備してバージョン1.0に到達しました?
バージョン1.0到達以降も、まだまだ様々な強化学習アルゴリズムを追加しようと開発が進んでいます。(この記事を準備している間にも、v1.1.0が公開されてます。)
インストール方法や基本となる使い方は、公式ReadMeや、前の記事を読んでいただければと思うので、この記事では割愛します。
この記事では、私もお手伝いさせてもらって整備したアルゴリズム以外の部分について紹介します。
2. マルチプラットフォームテスト (PR 97)
GitHub Actions によって、Windows/macOS/Ubuntu のマルチプラットフォームで、push や pull requestの度にユニットテストを自動で走らせれるようになりました。
特に、Windowsの開発機を友人も私も持っておらず、なかなかサポートできていなかったのですが、このActionsによってWindows上での問題があぶり出されWindowsでも無事動作できるようになりました。
(Windowsでは、multiprocessing.Pool
などを利用する際に渡すことができるのは、ネストしていないモジュール直下で定義されたクラス・関数だけみたいですね。なんでもfork()
システムコールの代わりに利用している pickleのシリアライズが原因みたいですが、なんでそこに制約があるのかまでは理解できていません。)同じコードを複数のTFとPythonのバージョンの関係もあって、下のように綺麗なマトリックス戦略になっていないのですが、もうちょっとうまく記述する方法はありませんかね。
.github/workflows/test.yml(抜粋)strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] python: ['3.7', '3.8'] TF: ['2.2', '2.3'] include: - os: ubuntu-latest python: '3.7' TF: '2.0' - os: ubuntu-latest python: '3.7' TF: '2.1' - os: macos-latest python: '3.7' TF: '2.0' - os: macos-latest python: '3.7' TF: '2.1' - os: windows-latest python: '3.7' TF: '2.0' - os: windows-latest python: '3.7' TF: '2.1'3. Super-Linterでコードの自動チェック (PR 102)
GitHub Super-Linterを利用し、元々手作業で行っていたLinterでのコードのルールチェックが自動化されました。
Super-Linterで躓いたのは、カスタム設定のファイルを
.github/linters/
ディレクトリに置かないといけないことでした。 カスタム設定のファイル名自体は、Super-Linterの起動時のオプションで指定できますが、あくまで上記のディレクトリにおいていないと見つからずデフォルトの設定が使用されてしまいます。(最終的にわからなくて質問しました。)4. Sphinx を利用したドキュメントサイト構築 (PR 107)
GitHub Actionsの中で、Sphinxを利用してドキュメントを自動生成しています。
docstring から自動でクラスリファレンスを生成する autodoc とMarkdown形式文書を取り込む recommonmark を有効にしています。(テーマはRead The Docsテーマとしました。)
conf.pyfrom recommonmark.transform import AutoStructify extensions = ["sphinx.ext.autodoc", "recommonmark"] html_theme = "sphinx_rtd_theme" def setup(app): app.add_transform(AutoStructify)ちょっとだけつまづいたのは、
sphinx-apidoc
コマンドで autodocの雛形となる一式をソースコードから生成するのですが、自動生成されるindex.rst
が 手作りのindex.md
より優先されてしまって、うまく表示ができなかったので(しばらく悩んだあとに)index.rst
を削除するコードを追加しすることで表示できるようになりました。GitHub Pagesへの公開は、MasterブランチかつFork先ではない時に、peaceiris/actions-gh-pagesを利用して公開しています。
(どうも、gh-pages
というブランチを作ってそこに生成物をpushする仕組みみたいです。なのでよくあるmaster
ブランチの doc以下を公開という設定とは異なります。).github/workflows/doc.yml(抜粋)- uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public if: (github.ref == 'refs/heads/master') && (github.repository == 'keiohta/tf2rl')Sphinxによって自動的に書き出されたクラスレファレンスはこちら
(クラスリファレンス以外のチュートリアルも自分で書きたいと聞いていたので、Markdownで書けるように環境は整備しましたが、まだ無いようです。。。乞うご期待。)5. Docker と GitHub Container Registry を利用した構築済みコンテナ環境の提供 (PR 111)
ログインせずともコンテナイメージをダウンロードできるGitHub Container Registryがベータ公開されたのに併せて、構築済みコンテナ環境を利用できるようにしました。(それ以前のGitHub Packagesはログインしないとpublicなイメージもダウンロードできないという謎仕様で、フォーラムでも何人もの人がおかしいって言い続けていました。)
docker run -it ghcr.io/keiohta/tf2rl/cpu:v1.1.0 bash
また、Linuxオンリーかつマルチプロセスでの学習(ApeX)でうまく行かない例が散見されるのでexperimentalという扱いですが、NVIDIAのGPUを利用できるGPUコンテナバージョンも準備しています。
(私がMacBook Proしかなく、NVIDIA GPUの刺さったマシンを手元に持っていないためデバッグが難しく、環境をもった有識者が支援してくれると助かります。)docker run --gpus all -it ghcr.io/keiohta/tf2rl/nvidia:v1.1.0 bash
GPUコンテナについては、こちらの記事が非常に詳しくてためになりました。
コンテナイメージのビルドは以下のように設定してあり、tagつきでpushされたら、ビルドしてそのtag名をもったコンテナイメージをGitHub Container Registryに格納する仕組みになっています。
.github/workflows/docker.ymlname: docker on: push: tags: - '**' jobs: build: runs-on: ubuntu-latest env: DOCKER_BUILDKIT: 1 steps: - uses: actions/checkout@v2 - uses: docker/build-push-action@v1 with: registry: ghcr.io repository: ${{ github.repository_owner }}/tf2rl/cpu tag_with_ref: true username: ${{ github.repository_owner }} password: ${{ secrets.GHCR_TOKEN }} dockerfile: Dockerfile always_pull: true - uses: docker/build-push-action@v1 with: registry: ghcr.io repository: ${{ github.repository_owner }}/tf2rl/nvidia tag_with_ref: true username: ${{ github.repository_owner }} password: ${{ secrets.GHCR_TOKEN }} dockerfile: Dockerfile.nvidia always_pull: truedocker/build-push-actionは v2 があるのですが、ログインが分離されて二度手間で、tagを手動で切り出さなければならず、使い勝手が悪かったので、あえて v1 で固定しています。
また、ベータ版だからなのか、GitHub Container Registryは、GitHub Actionsの自動生成されるシークレットでは認証が通らないので、Personal Access Tokenを作って設定する必要があります。
もうひとつ、忘れがちなのはGitHub Container Registry にpushされたイメージは初めはプライベートになっています。皆が使えるようにするには、
https://github.com/<ユーザー名>?tab=packages
から指定のイメージを選んで、ポチポチ公開設定する必要があります。6.
Trainer
をコマンドラインプログラム以外 (Jupyter Notebook等) からも実行可能に (PR 105)TF2RLは元々コマンドラインからのスクリプト実行を前提とした作りになっており、構築したモデルを学習させる
Trainer
クラスはargparse
と強く結合してしまっており、Jupyter Notebook上で利用するには(できなくはないが)ちょっと面倒であった。後方互換性を維持するかつ元のコードへの変更点を最小限にするために、
argparse
ではなくdict
が渡されたときには空のNamespace
を構築してその中にdict
指定のデータを詰め込むことにした。こうすることで、わざわざコマンドラインパラメータを模擬した文字列のリストを経由しないで、パラメータを設定できる。tf2rl/experiments/trainer.py(抜粋)if isinstance(args, dict): _args = args args = policy.__class__.get_argument(Trainer.get_argument()) args = args.parse_args([]) for k, v in _args.items(): if hasattr(args, k): setattr(args, k, v) else: raise ValueError(f"{k} is invalid parameter.")7. TensorFlow Probability のバージョンの自動指定 (PR 113)
最近TF2RLがTensorFlow Probability (TFP) を利用するようになったのですが、TFPは動作するTensorFlow (TF)のバージョンが決まっている割にはインストール時にいい感じにしてくれなくて、何も考えずにインストールするとバージョン非互換でエラーが発生することがありました。
そこで、TF2RLの setup.py に以下のコードブロックを追加し、ユーザーがインストール済みのTFのバージョンに応じて、インストールすべきTFPのバージョンを切り替える方式を導入しました。
setup.py(抜粋)tf_version = "2.3" # Default Version compatible_tfp = {"2.3": ["tensorflow~=2.3.0", "tensorflow-probability~=0.11.0"], "2.2": ["tensorflow-probability~=0.10.0"], "2.1": ["tensorflow-probability~=0.8.0"], "2.0": ["tensorflow-probability~=0.8.0"]} try: import tensorflow as tf tf_version = tf.version.VERSION.rsplit('.', 1)[0] except ImportError: pass install_requires = [ "cpprb>=8.1.1", "setuptools>=41.0.0", "numpy>=1.16.0", "joblib", "scipy", *compatible_tfp[tf_version] ]
~=
は、バージョンの最後の数字はアップデートを許容するシンタックスで、この場合はメジャーバージョンやマイナーバージョンの更新は許可しないが、バグフィックス(だと思われる)更新は許可するためにこうしてあります。TF2.4 が出たらエラーになりますが、それは他のTF2.4変更対応とともに対処することになるでしょう。
8. 最後に
TensorFlow は書きにくいから PyTorch って思っている方も結構いるようですが、TF 2.0 以降非常に書きやすくなっていると個人的には思います。
TF2RLのユーザーがもっと増えたらいいなと思っています。
TF2RLでも利用している経験再生(Experience Replay)用のライブラリ cpprb (GitHubミラー) を開発しています。
こちらもぜひ興味を持ってもらえると嬉しいです。
- 投稿日:2020-10-25T20:57:10+09:00
「API開発 + Swagger UIを利用したAPI検証」な環境をDockerで構築する
Swaggerを利用することでREST APIの仕様をドキュメント化できます。
SwaggerではREST APIの仕様をドキュメントしたファイルをSwagger Specと呼びます。Swagger UIとはSwagger Specの情報を反映させた静的ページを生成するツールのことを言います。
Swagger UIはSwagger Specの情報を可視化するだけでなく、画面上からREST APIを実行する機能も提供しています。今回は「開発中のAPIをSwagger Specでドキュメント化 → Swagger Specの情報が反映されたSwagger UIの画面からAPIリクエストの検証」という一連の作業が行えるDocker環境の構築手順について紹介します。
今回作成するDocker環境について
仕様は以下の通りです。
- docker-compose upだけで環境が準備できる
- 「/swagger-ui」でSwagger UIの画面が表示される
- 「/swagger-ui」以外はAPI用のエンドポイントとする
- Swagger Spec編集後、リロードでSwagger UIに変更内容が反映される
- APIはRuby on RailsのAPIモードで作成する
- DBはMySQLを利用
nginxをリバースプロキシとして利用することでAPIの開発環境とSwagger UIを組み合わせます。
図で表現すると以下のようになります。今回の利用する各種バージョンは以下の通りです。
- Ruby on Rails: 6.0.3.2
- Ruby: 2.7.1
- MySQL: 8.0.21
- nginx: 1.19.3
API開発環境をDockerに作成する
APIモードで作成する『Rails 6 x MySQL 8』Docker環境構築手順を参考に、RailsのAPIモードを利用してAPI開発環境を作成します。
Dockerfileとdocker-compose.ymlは以下の通りです。
DockerfileFROM ruby:2.7.1 # 作業ディレクトリを/rails_api_swaggerに指定 WORKDIR /rails_api_swagger # ローカルのGemfileをDokcerにコピー COPY Gemfile* /rails_api_swagger/ # /rails_api_swaggerディレクトリ上でbundle install RUN bundle installdocker-compose.ymlversion: '3' services: api: # Ruby on Railsが起動するコンテナ build: . ports: - '3000:3000' # localhostの3000ポートでアクセスできるようにする volumes: - .:/rails_api_swagger # アプリケーションファイルの同期 depends_on: - db command: ["./wait-for-it.sh", "db:3306", "--", "./start.sh"] db: # MySQLが起動するコンテナ image: mysql:8.0.21 volumes: - mysql_data:/var/lib/mysql # データの永続化 - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d command: --default-authentication-plugin=mysql_native_password # 認証方式を8系以前のものにする。 environment: MYSQL_USER: 'webuser' MYSQL_PASSWORD: 'webpass' MYSQL_ROOT_PASSWORD: 'pass' MYSQL_DATABASE: 'rails_api_swagger_development' volumes: mysql_data: # データボリュームの登録RailsのAPIモードでは静的ページを生成する機能は除外されているため、Swagger UIを直接Railsアプリケーションに組み込むことはできませんが、今回の方法を利用すればAPIモードでもSwagger UIを利用できます。
サンプルとなるAPIを作成します。
# コンテナをバックグランドで起動 $ docker-compose up -d # Eventを操作する機能(モデル、ビュー、コントローラー)を一括作成 $ docker-compose exec api rails g scaffold event title:string # eventsテーブルを作成 $ docker-compose exec api rails db:migrate # rails consoleでeventsのレコードを作成 $ docker-compose exec api rails c > event = Event.new(title: 'サンプルイベント') > event.save
localhost:3000/events
にアクセスして以下のようなレスポンスが返ってくればOKです。リバースプロキシの設定を行い、nginx経由でAPIにアクセスできるようにする
nginx経由でRailsアプリケーションにアクセスできるようリバースプロキシの設定を行ます。
default.confserver { listen 80; server_name localhost; # "/"にアクセスがあったときの処理 location / { proxy_set_header Host localhost; # アクセス元のホストをlocalhostにする proxy_pass http://api:3000; # apiコンテナの3000ポートにリクエストを送る } }nginxの設定ファイルは
/etc/nginx/nginx.conf
です。
設定ファイルにinclude /etc/nginx/conf.d/*.conf;
という記述があることからも分かるように、設定ファイルでは/etc/nginx/conf.d
配下の.conf
という拡張子の設定も読み込んでいます。つまり、
/etc/nginx/conf.d
配下に今回作成した設定ファイルを配置することで、nginxコンテナをリバースプロキシとして利用できます。docker-compose.ymlにnginxコンテナを追加します。
docker-compose.ymlservices: api: (略) db: (略) nginx: image: nginx:1.19.3 ports: - '80:80' command: [nginx-debug, '-g', 'daemon off;'] volumes: - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf depends_on: - api volumes: mysql_data:
[nginx-debug, '-g', 'daemon off;']
はデバッグモードによる起動方法です。1なお、swagger-uiのDockerイメージもnginxを利用していますが、
nginx.conf
にinclude /etc/nginx/conf.d/*.conf;
の記述がありません。
ですので、swagger-uiのDockerイメージを利用する場合だと今回のアプローチはうまくいかないので注意してください。コンテナ起動後、
localhost:80/events
にアクセスして以下のようなレスポンスが返ってくればOKです。Swagger UIをnginxに組み込む
/swagger-ui
にアクセスをしたらSwagger UIの画面が表示されるようにnginxにSwagger UIを組み込んでいきます。Swagger UIの画面はswagger-ui/distによって構成されています。
dist
配下のファイルをローカルにコピーし、nginxコンテナにバインドマウントすることで、Swagger UIをnginxに組み込みます。
dist
配下のファイルをすべてコピーしてきてもよいのですが、unpkgを利用することでindex.html
のみをコピーするだけでSwagger UIの画面が作成できます。 2index.html<!-- HTML for static distribution bundle build --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Swagger UI</title> - <link rel="stylesheet" type="text/css" href="./swagger-ui.css" > + <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css" > <style> html { box-sizing: border-box; overflow: -moz-scrollbars-vertical; overflow-y: scroll; } *, *:before, *:after { box-sizing: inherit; } body { margin:0; background: #fafafa; } </style> </head> <body> <div id="swagger-ui"></div> - <script src="./swagger-ui-bundle.js" charset="UTF-8"> </script> + <script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js" charset="UTF-8"> </script> - <script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script> + <script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-standalone-preset.js" charset="UTF-8"> </script> <script> window.onload = function() { // Begin Swagger UI call region const ui = SwaggerUIBundle({ url: "https://petstore.swagger.io/v2/swagger.json", dom_id: '#swagger-ui', deepLinking: true, presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset ], plugins: [ SwaggerUIBundle.plugins.DownloadUrl ], layout: "StandaloneLayout" }) // End Swagger UI call region window.ui = ui } </script> </body> </html>docker-compose.ymlを修正し、作成した
index.html
をnginxのデフォルトの公開ディレクトリである/usr/share/nginx/html
配下に配置します。docker-compose.ymlservices:![スクリーンショット 2020-10-25 18.23.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140792/22cf7096-e237-7c2e-3aa5-0959d4776657.png) api: (略) db: (略) nginx: image: nginx:1.19.3 ports: - '80:80' command: [nginx-debug, '-g', 'daemon off;'] volumes: - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf + - ./nginx/html/swagger-ui:/usr/share/nginx/html/swagger-ui depends_on: - api volumes: mysql_data:
/swagger-ui
にアクセスしたらindex.html
が表示されるようnginxの設定を追記します。default.confserver { listen 80; server_name localhost; location / { proxy_set_header Host localhost; proxy_pass http://api:3000; } # "swagger-ui"にアクセスがあったときの処理 location /swagger-ui { alias /usr/share/nginx/html/swagger-ui; } }コンテナ起動後、
localhost:80/swagger-ui
にアクセスして以下のような画面が表示されればOKです。ローカルのSwagger SpecがSwagger UI上に反映されるようにする
Swagger UIの
url
を変更することで参照するSwagger Specを変更できます。ローカルのSwagger Specを参照するように変更します。
index.html- url: "https://petstore.swagger.io/v2/swagger.json", + url: "./api.yml",上記の変更でローカル環境に配置された
./nginx/html/swagger-ui/api.yml
の内容がSwagger UIへ反映されます。なお、
./nginx/html/swagger-ui/
ディレクトリはバインドマウントされているので、ローカルでSwagger Spec編集後、リロードすればコンテナのSwagger UIに変更内容が反映されます。サンプルとして作成した
GET /events
を実行するSwagger Specは以下の通りです。api.ymlopenapi: 3.0.2 info: title: サンプルAPI version: 1.0.0 servers: - url: http://localhost:3000 tags: - name: イベント paths: /events: get: tags: - イベント description: イベント一覧取得 responses: 200: description: 成功 content: application/json: schema: type: array description: イベントの配列 items: $ref: "#/components/schemas/Event" components: schemas: Event: type: object properties: id: description: ID type: integer format: int64 example: 1 title: description: タイトル type: string example: サンプルイベント created_at: description: 作成日 type: string format: date-time example: 2020-04-01 10:00 updated_at: description: 更新日 type: string format: date-time example: 2020-04-01 10:00コンテナ起動後、以下のような画面が表示されればOKです。
CORSの設定をする
Swagger UIは
localhost:80
、APIはlocalhost:3000
で起動しています。
この状態でSwagger UIからAPIにリクエストを送るとオリジンをまたがっているためAccess to fetch at 'http://localhost:3000/events' from origin 'http://localhost' has been blocked by CORS policy
というエラーが発生します。CORSの設定を行い、Swagger UIからAPIリクエストが送れるようにします。
今回はrack-corsを利用してCORSの設定を行ます。Gemfilegem 'rack-cors'config/initializers/cors.rbRails.application.config.middleware.insert_before 0, Rack::Cors do unless Rails.env.production? allow do origins(['localhost', /localhost:\d+\Z/]) resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head] end end endコンテナ起動後、リクエストが正常に返ってくればOKです。
参考: CRUD操作を行うSwagger Spec
- GET /events
- POST /events
- GET /events/{id}
- PATCH /events/{id}
- DELETE /events/{id}
上記のエンドポイントに関するSwagger Specは以下の通りです。
api.ymlopenapi: 3.0.2 info: title: サンプルAPI version: 1.0.0 servers: - url: http://localhost:3000 tags: - name: イベント paths: /events: get: tags: - イベント description: イベント一覧取得 responses: 200: description: 成功 content: application/json: schema: type: array description: イベントの配列 items: $ref: "#/components/schemas/Event" post: tags: - イベント description: イベント登録 requestBody: content: application/json: schema: type: object properties: title: type: string example: サンプルイベント responses: 201: description: 作成 /events/{event_id}: get: tags: - イベント description: イベント詳細 parameters: - name: event_id in: path description: イベントID required: true schema: type: integer format: int64 example: 1 responses: 200: description: 成功 content: application/json: schema: type: object $ref: "#/components/schemas/Event" 404: description: event not found patch: tags: - イベント description: イベント更新 parameters: - name: event_id in: path description: id required: true schema: type: integer format: int64 example: 1 requestBody: content: application/json: schema: type: object properties: title: type: string example: サンプルイベント responses: 200: description: 成功 content: application/json: schema: type: object properties: activity: $ref: "#/components/schemas/Event" delete: tags: - イベント description: イベント削除 parameters: - name: event_id in: path description: id required: true schema: type: integer format: int64 example: 1 responses: 204: description: No Content components: schemas: Event: type: object properties: id: description: ID type: integer format: int64 example: 1 title: description: タイトル type: string example: サンプルイベント created_at: description: 作成日 type: string format: date-time example: 2020-04-01 10:00 updated_at: description: 更新日 type: string format: date-time example: 2020-04-01 10:00画面は以下のようになります。
まとめ
以上でAPIとSwagger UIを統合した開発環境の構築手順の紹介を終わります。
- nginxを利用することでSwagger UIとAPIを組み合わせる
- nginxのリバースプロキシ設定は『/etc/nginx/conf.d』配下に作成
- オリジンをまたがるリクエストをする際はCORSの設定が必要になる
- 自作のSwagger SpecをSwagger UIに反映させるにはindex.htmlのurlを変更する
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!
- 投稿日:2020-10-25T20:15:05+09:00
OKI AE2100 & Node-REDでローコードIoTしてみた。その2 構築編
DockerでローコードIoTプラットフォーム構築編
はじめに
これはOKIの「AIエッジコンピューター」と呼ばれる AE2100 というゲートウェイ製品にNode-REDを載せて、ローコードIoTのプラットフォームにしようという記事のその2、DockerでローコードIoTプラットフォーム構築編 になります。
その1 PythonでRS-485シミュレータ準備編
その2 DockerでローコードIoTプラットフォーム構築編 (本記事)
その3 Node-REDでローコードIoT実践編 1 ダッシュボード作成
その4 Node-REDでローコードIoT実践編 2 MQTT Pub/Sub前回の記事では、Windows 10 PC で動作する RS-485シミュレータを Python で作成しました。
今回はいよいよ AE2100 で Node-REDを立ち上げます。
内容としては、ほとんどDockerの作業になります。Dockerfile を作り、Dockerコマンドを数回たたくと、 AE2100 で Node-RED が立ち上がります。
こんなことやります
図の ❷ のNode-REDをインストールしたDockerイメージを作成します。
Dockerイメージの構築
SSH で AE2100 にログインして Bash 上で作業します。
Dockerfile
AE2100 で実行するDockerコンテナのイメージを作成するDockerfileです。
これだけでOKです。DockerfileFROM nodered/node-red:1.1.3-minimal USER root RUN apk add python3 make g++ linux-headers RUN npm install node-red-node-serialport node-red-dashboardこのファイルの内容ですが、まずFROM命令でベースとなるイメージを、Docker Hub にある nodered/node-red の最小イメージ 1.1.3-minimal に指定します。
そしてこの Alpine Linuxベースのイメージに root になって、Node-REDのシリアル通信ドライバのビルドに必要な以下の4つのパッケージを apk add します。
- python3
- make
- g++
- linux-headers
最後に、今回の作業に必要な以下の2つのNode-REDライブラリをここで npm install してしまいます。
- node-red-node-serialport
- node-red-dashboard
node-red-node-serialport は今回 AE2100 上の Node-RED で RS-485 を使うためのライブラリです。
このライブラリは名前が示す通り、RS-232C/RS-485/RS-422等シリアル通信機能をNode-REDに追加するライブラリになります。通常、RS-232C通信で良く使われるライブラリですが、RS-485でも問題なく使えました(マルチドロップは試していません)。node-red-dashboard はNode-REDで簡易ダッシュボードを作成するためのライブラリです。
非常によく利用されており、アップデートも頻繁に行われています。
本文執筆時のバージョンはそれぞれ 3.23.3 と 0.11.0 でした。この2つのライブラリはNode-REDが立ち上がってからインストールしても良いのですが、今回必須ということで、イメージの中に組み込んでしまいます。
Docker イメージのビルド
それでは AE2100 でイメージをビルドしてみます。
上記のDockerfileがあるディレクトリで以下を実行します。AE2100-Shell# docker build --tag node-red_v1:appf . : Successfully built 3691865b0133 Successfully tagged node-red_v1:appfnode-red-node-serialport のC++モジュールのビルドが始まると何やら赤字のログがたくさん出力されますが、"Successfully build..." が出れば大丈夫でしょう。
これで "node-red_v1:appf" のタグ名が付いたイメージができました。
公式のMinimalイメージ194MBに、もろもろ追加されて、計441MBのイメージになりました。。。
しかし 32GB の eMMC を搭載する AE2100 にとってはまだまだ余裕たっぷりです。Docker コンテナの実行
コンテナの立ち上げです!
Node-REDにアクセスする1880番ポートとMQTT用の1883番ポートをそのままコンテナで使えるようにします。
AE2100 の RS-485 のデバイスファイルは /dev/ttyRS485 です。これもそのままコンテナで使えるようにします。
そして AE2100 ホストの /home/root/.node-red ディレクトリをコンテナの /data にボリュームマウントして、Node-REDの設定ファイルやフローは AE2100 ホスト側のファイルシステムに保存するようにします。
Node-RED のフローやライブラリは頻繁に更新されますからね。# docker run -it -p 1880:1880 -p 1883:1883 --device=/dev/ttyRS485:/dev/ttyRS485 -v /home/root/.node-red:/data --name node-red-1 node-red_v1:appf > node-red-docker@1.1.3 start /usr/src/node-red > node $NODE_OPTIONS node_modules/node-red/red.js $FLOWS "--userDir" "/data" 8 Sep 23:27:27 - [info] Welcome to Node-RED =================== 8 Sep 23:27:27 - [info] Node-RED version: v1.1.3 8 Sep 23:27:27 - [info] Node.js version: v10.22.0 8 Sep 23:27:27 - [info] Linux 4.14.67-intel-pk-standard x64 LE 8 Sep 23:27:27 - [info] Loading palette nodes 8 Sep 23:27:29 - [info] Dashboard version 2.23.3 started at /ui 8 Sep 23:27:29 - [info] Settings file : /data/settings.js 8 Sep 23:27:29 - [info] Context store : 'default' [module=memory] 8 Sep 23:27:29 - [info] User directory : /data 8 Sep 23:27:29 - [warn] Projects disabled : editorTheme.projects.enabled=false 8 Sep 23:27:29 - [info] Flows file : /data/flows.json 8 Sep 23:27:29 - [info] Creating new flow file 8 Sep 23:27:29 - [warn] --------------------------------------------------------------------- Your flow credentials file is encrypted using a system-generated key. If the system-generated key is lost for any reason, your credentials file will not be recoverable, you will have to delete it and re-enter your credentials. You should set your own key using the 'credentialSecret' option in your settings file. Node-RED will then re-encrypt your credentials file using your chosen key the next time you deploy a change. --------------------------------------------------------------------- 8 Sep 23:27:29 - [info] Server now running at http://127.0.0.1:1880/ 8 Sep 23:27:29 - [info] Starting flows 8 Sep 23:27:29 - [info] Started flowsエラーなしに立ち上がったでしょうか?
Docker コマンドで確認してみますか。# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 122cd69c5b65 node-red_v1:appf "npm start --cache /…" 15 seconds ago Up 14 seconds (health: starting) 0.0.0.0:1880->1880/tcp, 0.0.0.0:1883->1883/tcp node-red-1実行時 "--name" オプションで指定した "node-red-1" という名前で動作しているようです。
Node-RED の実行確認
それでは PC のWebブラウザでこの Node-RED に接続してみましょう。
URLは以下のようになります。http://AE2100のIPアドレス:1880おなじみのフローエディタが表示されるはずです。
ネットワーク・パレットを見ると、一番下に "serial in"、"serial out"、"serial request" の3つのノードが追加されています。Dockerfile 内に記述した RUN 命令でインストールされた node-red-node-serialport ライブラリです。
MinimalのイメージでもMQTTやWebSocketのノードがあるのはさすがNode-REDですね。
ローコードIoT開発プラットフォームなので当然ですか。パレットの一番下 dashboard も Dockerfile 内でインストールしたライブラリ node-red-dashboard のノード達です。
先に少し説明しましたが、これにより本当に簡単にちょっとしたダッシュボードを作ることができ、デバッグ支援にも使えるし、必須ともいえる外部ライブラリではないでしょうか。
さいごに
以上で AE2100 ローコードIoT開発プラットフォームの完成です!
Node-RED が立ち上がってしまえば、Node-RED 経験者にはこれ以上説明することはないのですが、せっかくなので、Node-RED 初心者向けにIoTらしい簡単な実践編の記事を書くことにしました。
まずは RS-485シミュレータからセンサーデータを取り込んで、Webブラウザ上の簡易ダッシュボードに表示するアプリを作成します。
- 投稿日:2020-10-25T18:27:20+09:00
docker-compose --help 日本語訳
docker-compose --help
実行時に表示されるヘルプドキュメントの日本語訳。Docker を使用してマルチコンテナーアプリケーションを定義し、実行します。
使用法:
docker-compose [-f <arg>...] [options] [--] [COMMAND] [ARGS...] docker-compose -h|--helpオプション:
- -f, --file FILE 代替の compose ファイルを指定します(デフォルト:
docker-compose.yml
)- -p, --project-name NAME 代替プロジェクト名を指定します(デフォルト: ディレクトリ名)
- -c, --context NAME コンテキスト名を指定します。
- --verbose より多くの出力を表示します。
- --log-level LEVEL ログレベルを指定します。
- DEBUG
- INFO
- WARNING
- ERROR
- CRITICAL
- --no-ansi ANSI 制御文字を非表示にします。
- -v, --version バージョンを表示して終了します
- -H, --host HOST 接続するデーモンソケットを指定します。
- --tls TLS を使用します;
--tlsverify
によって暗示されます。- --tlscacert CA_PATH この CA によってのみ署名された信頼証明書
- --tlscert CLIENT_CERT_PATH TLS 証明書ファイルへのパス
- --tlskey TLS_KEY_PATH TLS キーファイルへのパス
- --tlsverify TLS を使用して接続を確認します
- --skip-hostname-check デーモンのホスト名をクライアント証明書で指定された名前と照合しないようにします
- --project-directory PATH 代替作業ディレクトリを指定します(デフォルト: compose ファイルのパス)
- --compatibility 設定されている場合 Compose は v3 ファイルのキーを Swarm 以外の同等のものに変換しようとします(非推奨)
- --env-file PATH 代替環境ファイルを指定します
Commands:
- build サービスのビルドまたは再ビルドを実行します
- config compose ファイルを検証して表示します
- create サービスを作成します
- down コンテナ、ネットワーク、イメージ、ボリュームを停止して削除します
- events コンテナからリアルタイムのイベントを受信します
- exec 実行中のコンテナでコマンドを実行します。
- help コマンドのヘルプを表示します。
- images イメージを列挙します。
- kill コンテナを停止します。
- logs コンテナからの出力を表示します。
- pause サービスを一時停止します。
- port ポートバインディングの為の公開ポートを表示します。
- ps コンテナを列挙します。
- pull サービスイメージをプルします。
- push サービスイメージをプッシュします。
- restart サービスを再起動します。
- rm 停止されたコンテナを削除します。
- run 一度限りのコマンドを実行します。
- scale サービスに使用するコンテナ数を指定します。
- start サービスを開始します。
- stop サービスを停止します。
- top 実行中のプロセスを表示します。
- unpause サービスの一時停止を解除します。
- up コンテナを作成して開始します。
- version バージョン情報を表示して終了します。
- 投稿日:2020-10-25T18:16:47+09:00
初心者向けCI/CD実践 - Part2 - CI/CDツール構築編
CI/CD環境を構築
本連載は、「CI/CDを実践してみたい」という超初心者向けの内容となっています
enterpriseレベルやproductionレベルの導入に際して、「CI/CDとは?」という感覚をつかむものとなれば幸いです。
利用するツール等はこちらで選定していますので、別のツールを利用する場合は、適宜お調べください。
大まかな内容としては、以下のようなフローとなります
- 環境構築
- CI/CDツールの構築<-今回はここを説明
- 開発プロジェクトの準備
- GitHubにプロジェクトデータを登録
- Jenkins Pluginのインストール
- 手動ビルド
- CI/CDツールとその他ツールの併用例
- VCSとの協調
- テストツールとの協調
- インスペクションツールとの協調
概要
- Jenkinsコンテナの実行
- Jenkins初期設定
- gmailを用いてビルド結果を自動通知
- JDK/Ant/Mavenの自動インストール
CI/CDツールの構築
CI/CDツールには、以下のようなものがある
- Jenkins
- Drone
- CircleCI
- AWS CodeBuild
- Tekton
今回は
Jenkins
を導入するJenkinsコンテナの実行
Jenkinsの公式を参考にJenkinsコンテナを実行し、初期設定を行う
最初にnetworkおよびvolumeの設定を行う
$ docker network create jenkins $ docker volume create jenkins-docker-certs //Dockerデーモンに接続するために必要なDockerクライアントのTLS証明書を共有 $ docker volume create jenkins-data //データ永続化に利用 $ docker network ls //新規作成されたbridge network及びdefaultの3つのnetworkがある $ docker volume ls続いて、jenkinsコンテナとして
jenkinsci/blueocean
を実行$ docker container run --name jenkins-blueocean --rm --detach \ --network jenkins --env DOCKER_HOST=tcp://docker:2376 \ --env DOCKER_CERT_PATH=/certs/client --env DOCKER_TLS_VERIFY=1 \ --volume jenkins-data:/var/jenkins_home \ --volume jenkins-docker-certs:/certs/client:ro \ --publish 8080:8080 --publish 50000:50000 jenkinsci/blueoceanこれで、jenkinsが実行される
jenkins dashboardへの初回ログイン
jenkinsのdashboardに入るためには、ブラウザ上で
http://localhost:8080/
と入力
passwordとして、コンテナを実行した際の値を入力
もしくは、下記コマンドを実行し初期パスワードを確認$ docker exec jenkins-blueocean cat /var/jenkins_home/secrets/initialAdminPassword続いて、pluginのインストールとユーザの作成を行う
Customizing Jenkins with pluginsにて以下のどちらかを選択
Install suggested plugins
(基本的にこちら)
Select plugins to install
ユーザの作成では、以下のようにadmin権限を持った新規ユーザを作成
これで初回ログイン時の設定は終了
jenkinsの初期設定
初期設定では、以下の2点に関して設定を行う
- ビルド結果のメール通知
- CI実現に必須なツールのインストール
初めに、「ビルド結果のメール通知」を設定
dashboard > 左ペインのJenkinsの管理
> 中央ペインのシステムの設定
>Jenkins Locationにて
Jenkins URL
,System Admin e-mail address
を入力
System Admin e-mail address
は通知メールの差出人E-mail Notificationにて以下のように設定
test mailの宛先を入力した後、Test configuration
をクリッククリック後に
Email was successfully sent
と表示されればメールが届いている
もし、Failed to send out e-mail
javax.mail.AuthenticationFailedException: 535-5.7.8 Username and Password not accepted. Learn more at 535 5.7.8 https://support.google.com/mail/?p=BadCredentials q14sm9594426pjp.43 - gsmtp ~~と表示された場合、Googleアカウントの「安全性の低いアプリのアクセス」が
無効
(defaultは無効)
有効にする場合は、こちらを参考にしてください続いて、「CI実現に必須なツールのインストール」を設定
dashboard > 左ペインのJenkinsの管理
> 中央ペインのGlobal Tools Configuration
>以下の通り入力しsave
JDKのインストールに当たって、Oracleアカウントが必須なため、リンク先からユーザ名とパスワードを入力(入力前は"I agree to the Java SE ~~"付近にエラーが表示されている)
もしアカウントを持っていない場合、そこからアカウント作成が可能
- 投稿日:2020-10-25T17:44:38+09:00
Code-Server用docker-compose.yml
自分用
docker-compose.yml
version: "2.1" services: coder: image: codercom/code-server container_name: Code-Server user: 0:0 volumes: - /root/projects:/root/project ports: - 8000:8000 entrypoint: "code-server --auth none --user-data-dir /root/project --bind-addr 0.0.0.0:8000" restart: unless-stopped結構な頻度で画面が出てすぐ切断されることがある。どうも処理が重くて追い付かないなどの理由(?)でhandshakeに10秒以上かかるとタイムアウトで切断する模様…
node.jsインストール
codercom/code-serverイメージのOSはDebianの模様。aptは使えるがnodeは使えないのでインストール。これ動かしたら猛烈に時間がかかるので注意。
apt update && apt install -y npm && npm install -g n && n stable && apt remove -y --autoremove npmDockerfileに書くならこれも必要。
ENV DEBIAN_FRONTEND=noninteractive
- 投稿日:2020-10-25T17:41:28+09:00
Exposedを使ってDBアクセス
kotlinでのDBアクセスにExposedを使ったので忘備録。
動作確認にはDockerでテスト用のDBをたてて確認しました。DOckerの環境構築は以下を参考にしました。
・WSL2とDockerの導入
https://qiita.com/KoKeCross/items/a6365af2594a102a817b・WSL2のメモリ枯渇対策
https://qiita.com/yoichiwo7/items/e3e13b6fe2f32c4c6120Exposedとは
Kotlinで書かれたSQLライブラリです。
https://github.com/JetBrains/Exposedサンプルプログラム
まずはDockerでDBを作成するためのdocker-compose.yamlファイル。
version: '3' services: db: image: postgres:12.3 ports: - 5433:5432 environment: POSTGRES_USER: admin POSTGRES_PASSWORD: admin POSTGRES_DB: test_db次にテーブル定義。
object Member : Table("member") { val id = integer("member_id").autoIncrement().primaryKey() val name = varchar("name", 50) val age = integer("age") }最後にメイン関数。
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.SchemUtils.create fun main() { Database.connect("jdbc:postgresql://localhot:5433/test_db", "org.postgresql.Driver", "admin", "admin") transaction { addLogger(StdOutSqlLogger) create(Member) Member.insert { it[id] = 1 it[name] = "abc" it[age] = 20 } Member.insert { it[id] = 2 it[name] = "efd" it[age] = 30 } for(member in Member.selectAll()) { println("${member[Member.id]}: ${member[Member.name]}: ${member[Member.age]}") } Member.update({Member.name eq "abc"}) { it[name] = "あいうえお" } for(member in Member.selectAll()) { println("${member[Member.id]}: ${member[Member.name]}: ${member[Member.age]}") } Member.deleteAll() drop(Member) } }やっつけですが、とりあえず一通りCRUDができることを確認できました。
- 投稿日:2020-10-25T14:25:04+09:00
8.Docker(docker buildの詳細、instruction)
docker buildコマンドの詳細
なぜdocker build実行時、dockerfileではなく、そのフォルダを指定するのか
docker build実行時、指定されたフォルダをdocker daemonに渡す。
docker damonがフォルダとDockerfileを元にdocker imageを作る。なので、Dockerfileだけでなく、フォルダも必要。
buildするフォルダのことを「 build context 」と言う。
このcontextを使って、docker daemonがdockerfileからdocker imageを作る。context ・・・ 環境や状況
なぜdocker build コマンドはbuild contextを使って、docker imageをbuildするのか
build時に、COPY, ADDなどのdocker instructionによって、build contextの中にあるファイルをdocker imageに組み込める。
docker daemonとは
・ dockerのオブジェクトを管理している。(実際に、コンテナやdocker imageを操作する)
・ docker composeなど他のDockerのツールとコミュニケーションする。dockerオブジェクト ・・・ コンテナ、イメージ、ネットワークなどのこと
docker CLIのコマンド(「 docker build 」 や 「 docker run 」など)で、dockerのオブジェクトを管理しているdocker daemonに命令を送っている。
docker build -f [docker file] [build context]
build contextの中にdockerfileがない場合や、他のdockerfileを作り、devとtestと分けている場合は、 「-f」オプションを使い、docker build することで特定のdockerfileを指定して、docker build できる。
開発環境とテスト環境で異なるdockerfileを持っている場合などに「-f」を用いて、dockerfileを指定し、docker buildすることがある。
Dockerfileの名前は、
開発系ではDockerfile.dev
テストではDockerfiel.test
のような形のファイル名にすることが多い。docker instruction
COPY
build時に、build contextの中にあるファイルをdocker imageに組み込める。
→ホストから何かファイルやフォルダをコンテナに渡せる。COPY [src][destination]
src ・・・ ホストのファイルのpath
destination ・・・ コンテナ内で目的のファイルをおくファイルのpath「COPY」と「ADD」は似ているが、基本的には「COPY」で問題ない。
ADD
build時に、build contextの中にあるファイルをdocker imageに組み込める。
→ホストから何かファイルやフォルダをコンテナに渡せる。圧縮されたtarファイルをdocker buildした時に、docker imageに送り、さらにそれを解凍してくれる。
ADD [src][destination]
※「COPY」で、フォルダごとdocker imageにしても良いが、docker daemonに情報を渡す際に時間がかかる。
よって、重たいファイルがある時は、tarファイルで圧縮してから「ADD」でdocker imageに送る方が良い。ENTRYPOINT
docker runした時のデフォルトのコマンドを指定できる。(CMDと同じ)
「ENTRYPOINT」では、docker runした時に上書きできない。
「CMD」では、docker runした時に上書きできる。「ENTRYPOINT」がDockerfileにある場合はCMDの書き方が変わる。
CMDの形は「ENTRYPOINT」に指定したこのコマンドの引数を指定する。例)
・ ENTRYPOINTなしの場合のCMD
CMD["ls", "--help", "引数", "引数", ・・・]・ ENTRYPOINTありの場合のCMD
ENTRYPOINT["ls"]
CMD["--help", "引数", "引数", ・・・]
※docker run [image] -laのように引数(オプション)は上書きできるENV
環境変数をDockerfileで指定できる。
pathを通す時によく使う。環境変数 ・・・ OSの上で動くあらゆるプロセスが情報を共有するために使う変数。keyとvalueの組み合わせ
ENV [key] [value]
ENV [key]=[value]WORKDIR
Dockerfile内に記載されているdocker instructionの実行をするディレクトリを変更できる。
WORKDIR [絶対パス]
Dockerfileでは各instructionが実行される場所はルート直下。
Dockerfile内で、RUNでcdコマンドで移動しても、RUNで次のコマンドが実行されるのはルート直下。
しかし、それだと不便な場合があるので、「WORKDIR」で絶対パスを指定して、それ以降のinstructionを指定されたパスのところで実行する。最後に
この記事は、かめさん( https://twitter.com/usdatascientist?s=21 )のudemyのdocker講座の( https://www.udemy.com/share/103aTRAEMfeVhaTXoB/ )書き起こしです。
※あくまで、自分のための書き残しとして投稿しているので、講座と異なる部分を含んでいる可能性があります。
かめさんのブログ( https://datawokagaku.com/docker_lecture/ )
- 投稿日:2020-10-25T13:30:37+09:00
初心者向けCI/CD実践 - Part1環境構築編
CI/CD環境を構築
本連載は、「CI/CDを実践してみたい」という超初心者向けの内容となっています
enterpriseレベルやproductionレベルの導入に際して、「CI/CDとは?」という感覚をつかむものとなれば幸いです。
利用するツール等はこちらで選定していますので、別のツールを利用する場合は、適宜お調べください。
大まかな内容としては、以下のようなフローとなります
- 環境構築
- CI/CDツールの構築
- CI/CDツールの基本的な利用例
- CI/CDツールとその他ツールの併用例
- VCSとの協調
- テストツールとの協調
- インスペクションツールとの協調
環境構築
環境構築編では、CI/CDを実践するに必要な環境を整えます
概要
- Windows 10に仮想化ソフトウェア
VirtualBox
を用意VirtualBox
で仮想マシンUbuntu
を作成Ubuntu
上でDockerコンテナの実行環境を構築既存環境
OS : Windows 10 Enterprise
プロセッサ : Intel Core i7
RAM : 16GB
システムの種類 : 64bit OS仮想化ソフトウェアの用意
今回CI/CDを実践するにあたって、仮想環境を用意する
仮想環境には、「ホスト型」と「ハイパーバイザ型」があり。今回は前者を構築
ホスト型の仮想環境を構築する「仮想化ソフトウェア」には以下のようなものがある
- VirtualBox
- VMware Workstation Player
- KVM
今回は「VirtualBox」を利用
インストールは既に済ませていたので、こちらを参考に進めてください
VirtualBoxのバージョンは6.1.14で実施
仮想マシンimageのダウンロード
仮想マシンのOSとしてUbuntuを利用する
imageのダウンロードはこちら
Ubuntuのバージョン情報等はこちらの通り
- Ubuntu Focal 20.04 (LTS)
- 64-bit PC (AMD64) desktop image
注意
その他のバージョンやimageを利用する場合はこちらまたは、こちらを参考にしてください
今回の検証では、仮想マシン上にコンテナとしてCI/CDツールを用意します
適切なOSを利用しないとdocker コンテナを利用できません仮想マシンの作成
こちらを参考に仮想マシン作成
設定値は基本的にdefaultを採用し、以下の値のみ変更
仮想マシンの初期設定
仮想マシンの設定は指示に迷うところは特にないかと思いますので、省略
その他、事前に設定しておくこととして以下のような内容があります。それぞれの設定はリンク先を確認
docker
最後に行う環境構築として、Docker Engineのインストールを行う
公式のこちらを参考に進めていく手順だけ抜き出したものが以下になります
1. Dockerレポジトリの準備
-$ sudo apt-get update
-$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
-$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
-$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
2. Docker Engineのインストール
-$ sudo apt-get update
-$ sudo apt-get install docker-ce docker-ce-cli containerd.io
-$ sudo docker run hello-world
3. 一般ユーザでDockerを利用できるよう設定
-$ cat /etc/group | grep docker
-sudo gpasswd -a $(whoami) docker
-$ cat /etc/group | grep docker
-sudo chmod 666 /var/run/docker.sock
4. Docker Composeのインストール
-sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
-sudo chmod +x /usr/local/bin/docker-compose
-docker-compose --version
- 投稿日:2020-10-25T13:30:37+09:00
初心者向けCI/CD実践 - Part1 - 環境構築編
CI/CD環境を構築
本連載は、「CI/CDを実践してみたい」という超初心者向けの内容となっています
enterpriseレベルやproductionレベルの導入に際して、「CI/CDとは?」という感覚をつかむものとなれば幸いです。
利用するツール等はこちらで選定していますので、別のツールを利用する場合は、適宜お調べください。
大まかな内容としては、以下のようなフローとなります
- 環境構築<-今回はここ
- CI/CDツールの構築
- 開発プロジェクトの準備
- GitHubにプロジェクトデータを登録
- Jenkins Pluginのインストール
- 手動ビルド
- CI/CDツールとその他ツールの併用例
- VCSとの協調
- テストツールとの協調
- インスペクションツールとの協調
環境構築
環境構築編では、CI/CDを実践するに必要な環境を整えます
概要
- Windows 10に仮想化ソフトウェア
VirtualBox
を用意VirtualBox
で仮想マシンUbuntu
を作成Ubuntu
上でDockerコンテナの実行環境を構築既存環境
OS : Windows 10 Enterprise
プロセッサ : Intel Core i7
RAM : 16GB
システムの種類 : 64bit OS仮想化ソフトウェアの用意
今回CI/CDを実践するにあたって、仮想環境を用意する
仮想環境には、「ホスト型」と「ハイパーバイザ型」があり。今回は前者を構築
ホスト型の仮想環境を構築する「仮想化ソフトウェア」には以下のようなものがある
- VirtualBox
- VMware Workstation Player
- KVM
今回は「VirtualBox」を利用
インストールは既に済ませていたので、こちらを参考に進めてください
VirtualBoxのバージョンは6.1.14で実施
仮想マシンimageのダウンロード
仮想マシンのOSとしてUbuntuを利用する
imageのダウンロードはこちら
Ubuntuのバージョン情報等はこちらの通り
- Ubuntu Focal 20.04 (LTS)
- 64-bit PC (AMD64) desktop image
注意
その他のバージョンやimageを利用する場合はこちらまたは、こちらを参考にしてください
今回の検証では、仮想マシン上にコンテナとしてCI/CDツールを用意します
適切なOSを利用しないとdocker コンテナを利用できません仮想マシンの作成
こちらを参考に仮想マシン作成
設定値は基本的にdefaultを採用し、以下の値のみ変更
仮想マシンの初期設定
仮想マシンの設定は指示に迷うところは特にないかと思いますので、省略
その他、事前に設定しておくこととして以下のような内容があります。それぞれの設定はリンク先を確認
docker
最後に行う環境構築として、Docker Engineのインストールを行う
公式のこちらを参考に進めていく手順だけ抜き出したものが以下になります
1. Dockerレポジトリの準備
-$ sudo apt-get update
-$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
-$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
-$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
2. Docker Engineのインストール
-$ sudo apt-get update
-$ sudo apt-get install docker-ce docker-ce-cli containerd.io
-$ sudo docker run hello-world
3. 一般ユーザでDockerを利用できるよう設定
-$ cat /etc/group | grep docker
-sudo gpasswd -a $(whoami) docker
-$ cat /etc/group | grep docker
-sudo chmod 666 /var/run/docker.sock
4. Docker Composeのインストール
-sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
-sudo chmod +x /usr/local/bin/docker-compose
-docker-compose --version
- 投稿日:2020-10-25T12:56:02+09:00
https-portalコンテナのタイムゾーンをJSTに変更する
https-portalをDockerコンテナで運用していますが、タイムゾーンがUTCのままになっているコンテナがあることに気が付いてしまいました。
ログ見るときに困るのでJSTに変えたいと思います。
- https-portal
タイムゾーンはUTCになっています。
$ docker-compose exec https-portal sh # date Sun Oct 25 03:36:07 UTC 2020docker-composeで設定してみます。
docker-compose.ymlversion: '3' services: https-portal: container_name: https-portal image: steveltn/https-portal:1 ports: - '80:80' - '443:443' restart: always environment: DOMAINS: 'example.net -> https://kusanagi01_httpd:8443 #production, example.com -> https://kusanagi02_httpd:8443 #local' ERROR_LOG: stderr ACCESS_LOG: stdout CLIENT_MAX_BODY_SIZE: 16M TZ: Asia/Tokyo #追加 networks: - shared-network networks: shared-network: external: trueコンテナを作り直します。
JSTに変更されたことを確認できました。$ docker-compose stop Stopping https-portal ... done $ docker-compose up -d Recreating https-portal ... done $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------- https-portal /init Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp $ docker-compose exec https-portal sh # date Sun Oct 25 12:49:10 JST 2020
- 投稿日:2020-10-25T12:25:14+09:00
symfony/http-kernelをphpstorm&dockerでphpunit&xdebug
1.ソースのダウンロード
2.dockerの設定
3.phpstormの設定1. ソースのダウンロード
git clone https://github.com/symfony/http-kernel.git2. dockerの設定
cd ./http-kernel mkdir docker touch docker/Dockerfile touch docker/php.ini touch docker-compose.ymlDockerfileFROM php:7.4 RUN pecl install xdebug \ && docker-php-ext-enable xdebug RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y gitphp.ini; timezone date.timezone = Asia/Tokyo ; error reporing log_errors = On error_log = /dev/stderr ; xdebug xdebug.remote_enable = 1 xdebug.remote_autostart = 1 xdebug.remote_connect_back = 1docker-compose.ymlversion: "3" services: php-cli: build: ./docker volumes: - ./:/var/www/html - ./docker/php.ini:/usr/local/etc/php/php.ini working_dir: /var/www/html composer: image: composer volumes: - ./:/app - ./docker/php.ini:/usr/local/etc/php/php.ini working_dir: /app3. Composer Install
docker-compose run composer install docker-compose run composer require --dev symfony/phpunit-bridgeちなみにphpunit/phpunitは使いません。1
The PHPUnit bridge is designed to work with all maintained versions of Symfony components, even across different major versions of them. You should always use its very latest stable major version to get the most accurate deprecation report.
使うとエラーが出ます。
docker-compose run php-cli ./vendor/bin/phpunit Tests/ [25-Oct-2020 07:28:39 Asia/Tokyo] PHP Fatal error: Trait 'Symfony\Bridge\PhpUnit\ExpectDeprecationTrait' not found in /var/www/html/Tests/Controller/ContainerControllerResolverTest.php on line 21注意
docker-compose run composer ./vendor/bin/simple-phpunitを一度実行させておくことで、symfony/phpunit-bridgeからphpunit/phpunitをインストールさせておく
3. phpstormの設定
File > Settings > Languages & Frameworks > PHP
phpstormがdockerのphpを実行するように設定します
追加の+ボタンクリックして、From Docker,...を選択
Docker-composeにチェックを入れ、dockerから実行させるphpのservice(この場合php-cli)を選択
OK押して、phpが読み込まれてversionなどが表示されてれば問題ありません
Phpunit
File > Settings > Languages & Frameworks > PHP > Test Frameworks
phpstormがdocker内のphpunitを実行するように設定します
追加の+ボタンから PHPUnit by Remote Interpreterを選択
- PHPUnit library の Path to phpunit.phar にチェック入れる
- Path to phpunit.pharに
/var/www/html/vendor/bin/simple-phpunit
- Test Runner の Default configulation file にチェック入れ、
/var/www/html/phpunit.xml.dist
いざ実行
editor右上の虫のアイコン左のセレクタでedit configurationを選択
画面が開いたら追加の+ボタンからPhpunitを選択し、下記のように設定
breakpointを貼って、simple-phpunitが選択されている状態で虫アイコンをクリック
- 投稿日:2020-10-25T12:05:45+09:00
Mac の VirtualBox の Ubuntu に SSH 接続して Docker をインストールするまでやる
1. Mac に VirtualBox をインストール
Homebrew のサイトでスクリプトを確認し、terminal で実行する
2020年10月25日時点では下記のスクリプト
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"Homebrew を利用して Mac に VirtualBox をインストールする
brew update && brew upgrade && brew upgrade --cask brew cask install virtualbox2. VirtualBox に Ubuntu をインストール
Ubuntu のイメージをダウンロードする
- Ubuntu.com - Get Ubuntu
virtualbox に Ubuntu をインストールする
- LIFESTYLE LAB - やっとできた!MacのVirtualBox上にUbuntuをインストールする方法
Ubuntu に Guest Additions をインストールする
- Qiita - MacでUbuntuを快適に使う
3. Ubuntu への SSH 接続を設定
- with FPGA - Mac 上のVirtual Box のUbuntu にSSH でアクセスしX転送する
Ubuntu にホストオンリーアダプタを設定する
- VirtualBox 上の Ubuntu の電源を落としておく
- VirtualBox > File > Host Network Manager... を選択する
- Create ボタンを押して vboxnet0 を作成する
- DHCP Server は Enable にチェックする
- Host Network Manager のウィンドウを Close する
- VirtualBox の Settings ボタンを押す
- Network タブを選択する
- Adapter 2 を選択する(選択できなければ VirtualBox をいちど再起動する)
- Enable Network Adapter にチェックを入れる
- Attached to: で Host-only Adapter を選択する
- OK ボタンを押す
Ubuntu に openssh-server をインストールする
VirtualBox 上の Ubuntu を起動し、terminal を開いて下記コードを実行する
sudo apt update && sudo apt upgrade sudo apt install openssh-server sudo systemctl enable ssh sudo systemctl restart ssh ip address
3: enp0s8
に 割り振られたinet
の IP アドレスを確認する。Mac からの SSH 接続を確立する
Mac の terminal で下記のような形式のコードを実行し、SSH 接続する
ただし、<user>
は Ubuntu 上のユーザー名、<ip>
は上記で確認した IP アドレス
例:ssh foo@192.0.2.0
ssh <user>@<ip>以降は Ubuntu に SSH 接続した Mac の terminal から全て操作する
4. Ubuntu に Docker をインストール
- docker docs - Install Docker Engine on Ubuntu
Uninstall old versions
sudo apt-get remove docker docker-engine docker.io containerd runc
SET UP THE REPOSITORY
Update the apt package index and install packages to allow apt to use a repository over HTTPS:
sudo apt-get update sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-commonAdd Docker’s official GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -Verify that you now have the key with the fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88, by searching for the last 8 characters of the fingerprint.
sudo apt-key fingerprint 0EBFCD88
Use the following command to set up the stable repository.
sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"INSTALL DOCKER ENGINE
Update the apt package index, and install the latest version of Docker Engine and containerd, or go to the next step to install a specific version:
sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.ioVerify that Docker Engine is installed correctly by running the hello-world image.
sudo docker run hello-world
sudo なしで docker を扱う
- docker docs - Manage Docker as a non-root user
sudo usermod -aG docker $USER newgrp docker docker run hello-world
- 投稿日:2020-10-25T02:34:46+09:00
DockerFileに最新のNode.jsを追加した話
他で作成していたイメージにNode.jsをインストールしたかったが、調べてもすぐには出てこなかったためメモ
前提
Rustでwasmを触ってみようとして必要だった。
busterベースのコンテナを使用。結論
こちらを追加した
ENV NODE_VERSION 15.0.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ && node --version \ && npm --versionやっていることとしては
アーキテクチャを取得
公式サイトのurlを叩く
展開ログに表示されたバージョン
+ node --version v15.0.1 + npm --version 7.0.3考えたこと
最初はaptでインストールを行ったがバージョンが古く(10前後だった記憶)、せっかくなので最新にしようと考えた。しかし適当に調べても"正しい"方法が見つからないためDockerHubへ。
https://hub.docker.com/_/nodeここから自分の使っているイメージと似たようなOS(今回はbuster)をベースにしているイメージのDockerFileへ飛ぶ。
そこからnodeをインストールしている箇所を抜き出し、自分のDockerFileに適用。(本当はチェックサムやら何やらがあったが削除してしまった)見事動いた。
以上。出典
https://hub.docker.com/_/node
https://github.com/nodejs/docker-node/blob/d58d7e65c4f92ef22a190b0ca835ce62464ff3ba/15/buster/Dockerfile
- 投稿日:2020-10-25T01:44:23+09:00
Java GradleからのDocker利用
今回に限らず巨人の肩に乗ってパッケージを便利にしてきますか。
前回のパッケージをさっくり作ったところからスタートします。
なお、繰り返しですがソースコードあります。
適宜ご覧ください(READMEの口調が荒いですがお許しくだされ)。導入プラグイン
今回利用するのは、米Palantir Technologies(データ分析業)の開発している、
docker pluginたちです。
「たち」というのは、docker, docker-run, docker-composeそれぞれに独立のプラグインがあるからですね。
https://github.com/palantir/gradle-docker
composeは今回はいいかなぁ...
ひとまずはgradleからcontainer起動までこぎつける、ここまでを扱います。各手順
1. Dockerfile作成
まぁこれなければ動きませんよね...
今回作ったのはこんな感じです。DockerfileFROM amazonlinux:latest RUN yum update -y &&\ yum upgrade -y &&\ yum install java-11-amazon-corretto-headless -y COPY ./build/libs/gradle-docker.jar /tmp/app.jar ENTRYPOINT ["java", "-jar", "/tmp/app.jar"]私はクラウド環境としてAmazon ECS / Fargate / EKS想定なのでamazonlinuxです(思考放棄)。
イメージサイズが重要であればubuntuやalpineでというのもありよりのありです。
alpineにcorretto突っ込むという荒業もできないことはないです...
Javaは11、LTSが無料で使えるのはありがたいですね。
ともかく、まずCOPYとENTRYPOINTはコメントアウトして、ちゃんと動くかまで確認します。2. docker起動をビルドスクリプトに記述
ここが難所ですね。
まずプラグインを記入します。build.gradleplugins { id 'java' id 'application' id 'idea' id 'eclipse' id 'com.palantir.docker' version '0.25.0' id 'com.palantir.docker-run' version '0.25.0' }それから、プラグインが持っているtask:dockerに対し、いろいろオプションを加えていくわけです。
copySpecの下りはわかりにくいですので後述します。build.gradledocker { // name: これはbuildされたコンテナイメージの名前になります。 // コロンで区切った右側はタグとして認識されます。 name "${project.name}:${project.version}" // いわずもがなDockerfileです。 // パスは.\つけても素でも動きます。 dockerfile file('Dockerfile') // Gradleのコピースペックを使って、ビルドした資材をpluginの利用先に持っていきます。 copySpec.from('build/libs').into('build/libs') // docker buildのキャッシュ利用off noCache true // 依存関係定義:gradle dockerしたら、その前段でgradle buildが走ります dependsOn tasks.build }これで、基本command lineで"gradle docker"としたら、走るはずです。
※DockerfileのCOPY/ENTRYPOINTはコメントアウトから戻してください。まぁせっかくなので、ええいままよとcontainer起動まで行きますか。
プラグインはもう入っているのでタスクのオプションを追加するだけです。
コンテナ起動オプションは、特に人それぞれ異なるので、
ドキュメントをきっちり読んでくださいね。build.gradledockerRun { //コンテナ名です。 name project.name // 起動するイメージ(dockerタスクで作ったやーつ) image "${project.name}:${project.version}" // コンテナをデーモン起動?:docker run "-d" <- こいつ daemonize false // 否、我顕現す // 君はマグロか?(stopしたらauto terminate) clean true // いかにも、マグロだ。 }と、これで以下のコマンドをたたけばひとまずものになるはずです。
$ ./gradlew docker $ ./gradlew dockerRun Hello World.ただ、もう少しやるべきことはあります。
3. fatJarをつくる
現在はライブラリがないのでちゃんと動きますが、
フレームワーク・ライブラリを突っ込むと、classNotFoundで落ちます。
かくなる上は、buildするjarファイルにライブラリjarを突っ込むしかない(わけではないが楽)。
これもpluginを使えば楽です。
ShadowJar、今回はこれを使いましょう。
まずプラグイン追加して、build.gradleplugins { id 'java' id 'application' id 'idea' id 'eclipse' id 'com.palantir.docker' version '0.25.0' id 'com.palantir.docker-run' version '0.25.0' id 'com.github.johnrengelman.shadow' version '6.1.0' // <-こいつ }それからタスクのオプションを追加します。
中にfinalizedByとあります。
これはdockerタスクを追加したときには伝えておりませんでしたが、
ちゃんとこのタスクが終わってから次のタスクに移るための明示です。
つまりこの場合、shadowJarタスクでjarを作り終わってからdockerタスクをさせたいということです。
後続するタスクのdependsOnをつけることで、確かにshadowJar->dockerで実行されます。
ただ、dockerタスクが動く前にshadowJarが完了することは保証されません。
正直ちょっと詰まりました...タスク依存ムズイ...build.gradleshadowJar { // jarタスクのを参照してくれないので、ここでもarchiveファイルは指定 archiveFileName = "${project.name}.jar" // 依存関係 finalizedBy tasks.docker }そして、前述のgradle docker/dockerRunコマンドでちゃんとイメージ作成・起動までこぎつけられたことでしょう。
内部での動き
dockerプラグイン君ですが、keyはイメージに突っ込むファイルです。
プラグインは/build/docker配下に資材(Dockerfile含)をため込み、
それをimageビルドに利用しています。
なので、dockerタスクのオプションでそれをしなければなりません。
プラグインはGradleの"copySpec"というAPIを使っています。
それで、
from /build/libs/*
to /build/docker/build/libs/*
こんな形でファイルをコピーさせているということですね。
それで、build/docker配下に同じくコピーされたDockerfileは、
その置き場所から./build/libs/your.jarを見つけ、COPYでイメージに突っ込んでいます。
ちなみに、task dockerのオプション file, copySpecを組み合わせて同様のことができます。build.gradledocker { name "${project.name}:${project.version}" dockerfile file('Dockerfile') files shadowJar.archiveFile.get() copySpec.into('build/libs') noCache true dependsOn tasks.shadowJar }filesオプションを事前に突っ込むことで、それもcopySpecに載せられます。
これを利用し、jarに梱包しない環境ファイルが別にある場合もイメージに突っ込めます。開発に利用するなら
釈迦に説法かもしれませんが、
Dockerfileは書き換えての開発をお勧めします。
毎回gradle dockerでイメージビルドするのに、jdk落としてインスコしては萎えますので。
いっそjava環境まで作ったイメージをつくり、
以降はその部分をコメントアウトしてFROMを作ったイメージに向けるほうが圧倒的コスパです。だそく
しかしこのプラグイン群すさまじいですね、やれることが多くて。
それこそimage pushやcompose利用など、いろいろできます。
こうしたものがあり、利用できるからエンジニアやれているのだと常々感じます。ところで、話変わりますが「巨人の肩に乗る」って比喩でなくほんとに巨人なんですね。
SFの話です。
テューリアンは優しい。
それから、ちょっと面倒なので、docker rmiもgradleタスクで作ろうと思います。
プラグインに期待するのも1つですが、まぁできないことはないだろうと。
- 投稿日:2020-10-25T01:11:59+09:00
Dockerで環境構築 初心者編
dockerを使った環境構築を行ったのでその手順をご紹介します。
初めてdockerで環境構築を行ったので、少しでも参考になればと思います。環境
環境 バージョン PHP 7.0.27 FW CakePHP3.2.13 Apache 2.2.15 OS CentOS6.9 DB MySQL5.6.39 手順
- DockerフォルダDL
- Git Clone
- Docker コンテナに入る
- Apache起動
- ドキュメントルート設定
- Composer install
- mysql起動
- データベース作製
- app.phpの設定
- データベース接続
環境構築してみよう
DockerフォルダDL
今回は元々用意していたDockerFile,ymlファイルなどをまとめてダウンロードしてます。
下記、フォルダ構造になります。-/ |- docker-compose.yml |- docker |- db | |- Dockerfile | |- files | |- entry.sh | |- my.cnf | | |- web |- Dockerfile |- files |- composer.phar |- dev.conf |- php.ini |- ssl.confGit Clone
githubにてプロジェクトの取得。
フォルダ構造は下記のようになりました。
-/ |- project |- docker-compose.yml |- dockerDockerコンテナに入る
コンテナに入る前にイメージの作製、コンテナを起動します。
コマンドラインで下記を実行する。
ビルド
docker build // ビルドすることでdocker fileからイメージが得られます。コンテナの起動
$ docker-compose up -d // コンテナを起動します。
下記のコマンドで、ビルドとコンテナの起動を一度に行えます。ビルドとコンテナの起動
$ docker-compose up -d --build // イメージのビルドから始めてコンテナを起動します。$ docker ps //起動中のコンテナの確認
オプション-dについて
$ docker-compose up // ターミナルでコンテナを起動しているため、同じターミナルでは作業できない。 $ docker-compose up -d // コンテナをバックグラウンドで起動するため、同じターミナルで作業ができる。下記のコマンドでコンテナに入ります。
$ docker exec -it CONTAINER ID /bin/bash //CONTAINER IDは docker psをした際に確認できます。
Apache起動
webコンテナ内で、下記コマンドでApache起動する。service httpd start Apache起動 service httpd stop Apache停止 service httpd restart Apache再起動 /etc/init.d/httpd status Apache状態確認ドキュメントルート設定
web内のhttpd.confのドキュメントルートの設定を確認します。
今回のディレクトリ構造だとvar/www/htmlで問題なさそうです。composer install
composer installができませんでした。
アクセス権限の問題だと思い、アクセス権限777に変更しました。
アクセス権限に関しては下記の記事を参考にしました。
https://qiita.com/t-a-run/items/239ed690ece7a011804a下記、実行できました。
因みに、composer installはprojectフォルダで行いました。
compser installこの状態でアクセスするとデータベースエラーとブラウザに表示されます。
エラーの内容は、そのような(接続した)ファイルは見つからない。
database error(SQLSTATE[HY000] [2002] No such file or directorymysql起動
mysqlを動作させます。
webコンテナに入った時、同様にdbコンテナに入ります。service mysqld status //mysqlの起動状態の確認 service mysqld start //mysqlの起動ログイン前に初期のユーザー名とパスワードを確認します。
DBコンテナ内でmysqld.logを確認します。
cat mysqld.log
A temporary password is〜に書いてあるユーザー名パスワードを取得。
ユーザー名:rootデータベースにログインします。
docker exec -it コンテナID mysql -u root -pパスワード再設定->データベース作製->テーブル作成をおこないます。
app.phpの設定
git clone時には、app.phpは含まれていません。作成しましょう。
-/ |- project |- config |-app.php
app.phpの書き方はネットで検索すると出てきます。今回は他で使っていたファイルをそのままコピーして中身を編集しました。主にデータベースのしか触っていないです。
'Datasources' => [ 'default' => [ 'className' => 'Cake\Database\Connection', 'driver' => 'Cake\Database\Driver\Mysql', 'persistent' => false, 'host' => 'localhost', /** * CakePHP will use the default DB port based on the driver selected * MySQL on MAMP uses port 8889, MAMP users will want to uncomment * the following line and set the port accordingly */ //'port' => 'non_standard_port_number', 'username' => 'root', 'password' => 'データベース作成時に設定したパスワード', 'database' => 'データベース作成時に設定したパスワード', 'port' => ポート番号, 'encoding' => 'utf8', 'timezone' => 'UTC', 'flags' => [], 'cacheMetadata' => true, 'log' => false,cat mysqld.log
A temporary password isに書いてあるパスワードを取得
->dbコンテナでmysqlをrestartし、ログイン->パスワード再設定->データベース作製->テーブル作成->データベース接続
sequel proを使い、クイック接続にて接続テストを実行しました。
無事に接続完了しました。ブラウザでlocalhostと検索すると無事開けました。
参考資料
docker-compose.yml の内容を理解しよう
https://futureys.tokyo/lets-understand-contents-of-docker-compose-yml/Docker compose ことはじめハンズオン
https://qiita.com/TsutomuNakamura/items/7e90e5efb36601c5bc8aDockerfileの書き方と使い方
https://blog.codecamp.jp/docker-file-how-to起動中の docker コンテナのシェルに入る
https://qiita.com/sekizo/items/27cc9b406332afc674f6データベース作製
https://noumenon-th.net/programming/2019/04/01/docker-entrypoint-initdb01/chmodで設定する権限の書き方
https://qiita.com/irasally/items/6ebc3c68e22905fb7330
- 投稿日:2020-10-25T01:01:39+09:00
Javaジャーニー:快適なパッケージを求めて
ほぼ動的型付け言語しか使用しないチームに転職し、
┌( ^o^┌ )┐ <- これのごとく型付けェ型付けェと禁断症状に...
欲求不満に任せ、いつのまにか理想のGradleパッケージのジャーニーへと旅立っていました。
せっかくなので情報整理がてらやりたいこと・過程を紹介します。
あと、Githubにpublicのrepositoryを作っているので、
それをご覧いただくもよし、そのまま流用するもよし(そんな価値があればよいですが...)。
Github Link: gradle-docker
※本記事はJava/Gradle/Dockerなど基礎知識はすでにある前提でお読みください。やりたいこと
- Dockerにすんなり疎通できる
- テストのフローはきっちり(Junit*Matcher - Jacocoでカバレッジ)(YET)
- Logも今風(slf4j*logback - Jsonized Log)(YET)
- 書き方も統制しよう(formatter, linter)(YET)
ここまでやれば、まぁ禁断症状は治まるかと...
あと、これをベースにAWSのコンソール操作を自動化するツールも作るつもりなので...プロローグ
生まれたての小鹿パッケージ、作るだけ、作りますか。
gradle initの時の選択肢は、まぁオーソドックスですね。
javaですし、DSLはgroovyですし、テストはJUnitですし?。$ cd '任意のディレクトリ' $ mkdir 'project name' $ cd 'project name' $ gradle init --type java-application $ gradle wrapperこれで、よくある、ローカルにjavaさえ入っていれば
- maven,gradleなくともできますよ、
- gradleは固定ですよ
の環境が出来上がりですね。
あとは最低限のプロジェクト・パッケージ情報をシコシコ仕込みますか。gradle.buildplugins { id 'java' id 'application' id 'idea' id 'eclipse' } repositories { mavenCentral() } // パッケージのバージョン指定 project.version = '0.1.1' // javaランタイムは11(15はそのうち...) sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 dependencies { testImplementation 'junit:junit:4.13' } // Runするとき、Appのmain関数を起点に指定 application { mainClassName = 'info.akotadakura.App' } // UTF-8強要します。 tasks.withType(JavaCompile).all { options.encoding = "UTF-8" } // java -jarするとき、Appのmain関数を起点に指定 // あとjarファイル名にバージョンつくの嫌だ! jar { archiveFileName = "${project.name}.jar" manifest { attributes 'Main-Class' : 'info.akotadakura.App' } }実に初々しい...
と、ここにいろいろ付け加えていくことになります。
まずはコンテナ対応、Docker Nativeな時代ですからね。P.S.
初投稿なので、まさかりはお手柔らかに.....
- 投稿日:2020-10-25T01:01:39+09:00
Gradleジャーニー:快適なパッケージを求めて
ほぼ動的型付け言語しか使用しないチームに転職し、
┌( ^o^┌ )┐ <- これのごとく型付けェ型付けェと禁断症状に...
欲求不満に任せ、いつのまにか理想のGradleパッケージのジャーニーへと旅立っていました。
せっかくなので情報整理がてらやりたいこと・過程を紹介します。
あと、Githubにpublicのrepositoryを作っているので、
それをご覧いただくもよし、そのまま流用するもよし(そんな価値があればよいですが...)。
Github Link: gradle-docker
※本記事はJava/Gradle/Dockerなど基礎知識はすでにある前提でお読みください。やりたいこと
- Dockerにすんなり疎通できる
- テストのフローはきっちり(Junit*Matcher - Jacocoでカバレッジ)(YET)
- Logも今風(slf4j*logback - Jsonized Log)(YET)
- 書き方も統制しよう(formatter, linter)(YET)
ここまでやれば、まぁ禁断症状は治まるかと...
あと、これをベースにAWSのコンソール操作を自動化するツールも作るつもりなので...プロローグ
生まれたての小鹿パッケージ、作るだけ、作りますか。
gradle initの時の選択肢は、まぁオーソドックスですね。
javaですし、DSLはgroovyですし、テストはJUnitですし?。$ cd '任意のディレクトリ' $ mkdir 'project name' $ cd 'project name' $ gradle init --type java-application $ gradle wrapperこれで、よくある、ローカルにjavaさえ入っていれば
- maven,gradleなくともできますよ、
- gradleは固定ですよ
の環境が出来上がりですね。
あとは最低限のプロジェクト・パッケージ情報をシコシコ仕込みますか。gradle.buildplugins { id 'java' id 'application' id 'idea' id 'eclipse' } repositories { mavenCentral() } // パッケージのバージョン指定 project.version = '0.1.1' // javaランタイムは11(15はそのうち...) sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 dependencies { testImplementation 'junit:junit:4.13' } // Runするとき、Appのmain関数を起点に指定 application { mainClassName = 'info.akotadakura.App' } // UTF-8強要します。 tasks.withType(JavaCompile).all { options.encoding = "UTF-8" } // java -jarするとき、Appのmain関数を起点に指定 // あとjarファイル名にバージョンつくの嫌だ! jar { archiveFileName = "${project.name}.jar" manifest { attributes 'Main-Class' : 'info.akotadakura.App' } }実に初々しい...
と、ここにいろいろ付け加えていくことになります。
まずはコンテナ対応、Docker Nativeな時代ですからね。P.S.
初投稿なので、まさかりはお手柔らかに.....