- 投稿日:2019-07-04T23:32:15+09:00
【Laravel初心者による備忘録】Laravelデータベースの基本!
Laravelでデータベースを使うなら
Laravelでデータベースを使うなら、DBクラスかEloquentのどちらかを使います。
DBクラス
データベースアクセスのための基本的な機能をまとめたクラス。クエリビルだという機能も用意されている。
Eloquent
ORMを実装したもの。
ORMの説明(Wikipediaより引用)
データベースとオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。オブジェクト関連マッピングとも呼ぶ。
前提知識 CRUD
データベース操作の基本はCRUD(Create,Read,Update,Delete)の実装です。
SQLでは(INSERT,SELECT,UPDATE,DELETE)が対応する。1.DBクラス
必要な手続き
データベースを設定する
config/database.phpの冒頭にある'default'の第二引数を使用したいデータベース名に設定すればOK。sqliteならsqlite、MySQLならmysql。
'default' => env('DB_CONNECTION', データベース名),環境変数を設定する
.envファイルに環境変数がまとめられているので、この中のDB_CONNECTIONとDB_DATABASEを編集する。
DB_CONNECTION=データベース名 DB_DATABASE=使用するデータベースファイルのパスを指定コントローラの修正
DB:selectで指定したSQL文を実行し、データベースからレコードの情報を取り出します。
use Illuminate\Support\Facades\DB; $変数 = DB::select(実行するSQL文);DBクラス内でのCRUD
冒頭でCRUDについて述べたと思うのですが、DBクラスでは以下の静的なメソッドを用います。
CRUD メソッド C DB::insert(クエリ文,パラメータ配列); R DB::select(実行するSQL文); U DB::update(クエリ文,パラメータ配列); D DB::delete(クエリ文,パラメータ配列); テンプレートの修正
@foreachディレクティブなどを使用してデータを活用します。
ディレクティブに関しては以下の記事に記載してあります。クエリビルダ
LaravelのDBクラスにはクエリビルダという機能が用意されています。
クエリビルダ=SQLのクエリ文を生成するために用意されたメソッド2.Eloquent
必要な手続き
データベースを設定する
config/database.phpの冒頭にある'default'の第二引数を使用したいデータベース名に設定すればOK。sqliteならsqlite、MySQLならmysql。
'default' => env('DB_CONNECTION', データベース名),環境変数を設定する
.envファイルに環境変数がまとめられているので、この中のDB_CONNECTIONとDB_DATABASEを編集する。
DB_CONNECTION=データベース名 DB_DATABASE=使用するデータベースファイルのパスを指定モデルの作成
artisanコマンドでモデルを作成します。作成されたモデルはappフォルダに配置されます。
php artisan make:model モデル名便利なツール
シーディングとマイグレーションはどちらの手法でも使える便利なものです。
シーディング
シード=最初から用意しておくコード
シーディングとはシードを作成する機能のこと。
初期状態でダミーのデータがあると便利。シーダーファイルの作成
artisanコマンドでシーダーファイルを作成します。作成されたシーダーファイルはdatabase/seedsフォルダの中に配置されます。
php artisan make:seeder シーダー名このファイルのrunメソッドにシーディング処理を記入します。
シーディングの登録
このシーダーファイルをdatabase/seeds/DatabaseSeeder.phpに登録します。
runメソッドに以下のように記入してください。$this->call(シーダークラス::class);シーディングの実行
以下のコマンドを使用してシーディングを実行します。
php artisan db:seedマイグレーション
現在使っているデータベースと全く同じ構造を再現するための仕組みのこと。データベースの移行したり、環境を移行したりする際に一からデータベースを作り直しのは大変。データベースを効率よく管理したいなら、マイグレーションを利用するべき!
マイグレーションファイルの生成
以下のコマンドを実行してマイグレーションファイルを作成します。
php artisan make:migration ファイル名database/migrationsの中に生成したマイグレーションが追加されます。
生成したファイルの中にはMigrationを継承したクラスが作成されています。このクラスにつのメソッドが用意されています。
- upメソッド(テーブルを生成するための処理)
- downメソッド(テーブルを消去するための処理)
それぞれ必要な処理を記述します。
主要な型の設定
説明 コマンド プライマリキー $table->increments(フィールド名); 整数 $table->integer(フィールド名); 実数 $table->float(フィールド名); 文字 $table->String(フィールド名); 真偽値 $table->boolean(フィールド名); 日時 $table->dateTime(フィールド名); NULL値可能なcreated_atとupdated_atカラム追加 $table->timestamps(); マイグレーションの実行
以下のコマンドを実行してマイグレーションを実行する。
php artisan migrateコンソールにメッセージが出力され、テーブルが用意される。
多くのチュートリアルでは・・・
以下のチュートリアルでは、マイグレーションを作成しEloquentを用いてデータベースを作成していました。
- 【Laravel 5.7対応】掲示板を作成するチュートリアル
- Laravel5.4でシンプルなCMSを作るチュートリアル
- Laravel 5.5 入門として「基本のタスクリスト」を作成する [その1]
個人的に苦しんだエラー特集
以下の記事を参考にしてDockerの環境を構築しました。
目的(機械学習のついでに、ローカルを汚さないようにするために...など)が果たせればOKと判断して雰囲気でDocker使ってたので、今回苦労しました(・・;) 夏休みあたりにちゃんとDocker勉強します?
Dockerでマイグレーションが作成できない
.envの
DB_HOSTをデフォルト設定から変更する必要がある。docker-compose.ymlでserviceとして定義した名前を使用する。phpMyAdminにログインできない
環境変数内(.env)のユーザーネーム、パスワード、サーバ名、全て同じものを使用してログインを試みたのに何度試しても失敗。
もう一度コンテナを作り直したら解決した。原因不明?
このエラー解消に恐ろしく時間取られたのが本当に悔しい...!参考
- 投稿日:2019-07-04T22:33:26+09:00
Simh/i1401 with COBOL on docker(2)
Simh/i1401 with COBOL on docker(1)ではCOBOLコンパイラのテープイメージを作成しました。
これを使ってCOBOLプログラムを実行します。
cobol.iniはWindows用ですので、Linux用を用意します。cobol_linux.iniSET CPU 16K set CPU NEWCONVERSIONS SET CDP BUSINESS SET LPT BUSINESS at mt3 -n scratch.mt3 at mt4 -n scratch.mt4 at mt5 -n scratch.mt5 at mt6 -n scratch.mt6 at mt1 Cobol.tap at cdr %1 ; output printer output to a file at lpt -n printer.txt ; output printer output to console ; SET LPT DEFAULT d ssa 1 d ssb 0 d ssc 1 d ssd 0 d sse 0 ; Sense Switch F: ON=if IOCS generation by cobol is not desired d ssf 1 ; Sense Switch G: ON=if the cobol source symbolic listing option is used d ssg 1 boot mt1 ; now compile cobol ; stops to ask for output det lpt echo echo === Now cobol compilation printer output will be listed === echo echo !cat printer.txt echo echo === end of printer output === echo at lpt printer.txt ; Sense Switch B: ON for punched autocoder d ssb 1 ; Sense Switch D: ON for printed listing d ssd 1 at cdp -n obj_deck.s cont ; now assemble the generated autocode program ; now generating object deck det lpt echo echo === Now autocode generated program printer output will be listed === echo echo !cat printer.txt echo echo === end of printer output === echo bye :endまた、アセンブルするautocoder.iniもWindows用ですのでLinux用を用意します。
autocoder_linux.iniSET CPU 16K set CPU NEWCONVERSIONS SET CDP BUSINESS SET LPT BUSINESS at mt1 Autocoder.cobol.tap at mt3 -n scratch.mt3 at mt4 -n scratch.mt4 at mt5 -n scratch.mt5 at mt6 -n scratch.mt6 at cdr obj_deck.s at cdp -n obj_deck.crd ; output printer output to a file at lpt printer.txt ; output printer output to console ; SET LPT DEFAULT dep ssa 1 boot mt1 ; autocode assembling done. ; Reset the computer to load assembled program dep ssf 0 cont det lpt echo echo === Now autocode assembly printer output will be listed === echo echo !cat printer.txt echo echo === end of printer output === echo det cdr echo echo ; Now run the compiled program reset at mt3 -n scratch.mt3 at mt4 -n scratch.mt4 at mt5 -n scratch.mt5 at mt6 -n scratch.mt6 at cdr obj_deck.crd at cdp -n out_deck.crd set lpt default dep ssa 1 ; set -n console log=a.log echo boot cdr bye :end準備ができたので、COBOLプログラムをコンパイルします。
/simh/generation # cd .. /simh # wget http://ibm-1401.info/pictures/000COBOL/i1401-Cobol.zip Connecting to ibm-1401.info (45.40.183.1:80) i1401-Cobol.zip 100% |****************************************************************| 170k 0:00:00 ETA /simh # unzip i1401-Cobol.zip Archive: i1401-Cobol.zip inflating: Cobol/Autocoder.cobol.tap inflating: Cobol/autocoder.ini inflating: Cobol/cobol.ini inflating: Cobol/Cobol.tap inflating: Cobol/Hello.cob inflating: Cobol/obj_deck.crd inflating: Cobol/obj_deck.s inflating: Cobol/out_deck.crd inflating: Cobol/printer.txt inflating: Cobol/run Cobol Hello World.bat inflating: Cobol/scratch.mt3 inflating: Cobol/scratch.mt4 inflating: Cobol/scratch.mt5 inflating: Cobol/scratch.mt6 /simh # cd Cobol /simh/Cobol # cp ../generation/Autocoder.cobol.tap . /simh/Cobol # cp ../generation/Cobol.tap . /simh/Cobol # cp ../cobol_linux.ini . /simh/Cobol # dos2unix Hello.cob dos2unix: converting file Hello.cob to Unix format... /simh/Cobol # i1401 cobol_linux.ini Hello.cob IBM 1401 simulator V4.0-0 Current git commit id: 9e719822 /simh/Cobol/cobol_linux.ini-7> at mt3 -n scratch.mt3 MT: creating new file: scratch.mt3 /simh/Cobol/cobol_linux.ini-8> at mt4 -n scratch.mt4 MT: creating new file: scratch.mt4 /simh/Cobol/cobol_linux.ini-9> at mt5 -n scratch.mt5 MT: creating new file: scratch.mt5 /simh/Cobol/cobol_linux.ini-10> at mt6 -n scratch.mt6 MT: creating new file: scratch.mt6 /simh/Cobol/cobol_linux.ini-12> at mt1 Cobol.tap Tape Image 'Cobol.tap' scanned as SIMH format. contains 254296 bytes of tape data (332 records, 1 tapemarks) A potentially unreasonable number of record sizes(165) vs tape marks (1) have been found The tape format (SIMH) might not be correct for the 'Cobol.tap' tape image /simh/Cobol/cobol_linux.ini-16> at lpt -n printer.txt LPT: creating new file: printer.txt HALT instruction, IS: 2830 (B 2063 'B) === Now cobol compilation printer output will be listed === TAPE COBOL COMPILATION VER 2 MOD 11 16K SEQUENCE CARD-IMAGE IDENTIFICATION 1 001010 IDENTIFICATION DIVISION. * 2 001020 PROGRAM-ID. @DISP-IBM-1401-SAMPLE@. * 3 001030 ENVIRONMENT DIVISION. * 4 001040 CONFIGURATION SECTION. * 5 001050 SOURCE-COMPUTER. IBM-1401 * 6 001060 MEMORY SIZE 8000 CHARACTERS * 7 001070 NO-RELEASE NO-PRINT-STORAGE. * 8 001080 OBJECT-COMPUTER. IBM-1401 * 9 001090 MEMORY SIZE ADDRESS 400 THRU 8000 * 10 001100 NO-OVERLAP NO-PRINT-STORAGE. * 11 002010 DATA DIVISION. * 12 002020 WORKING-STORAGE SECTION. ** 13 002030 01 FIELD PICTURE X%4). ** 14 003010 PROCEDURE DIVISION. ** 15 003020 START. * 16 003030 DISPLAY @HOLA COBOL@. ** 17 003040 MOVE @TEST@ TO FIELD. ** 18 003050 DISPLAY FIELD. ** 19 009999 STOP RUN. ** ** COBOL DICTIONARY ** DATA NAMES 13 A10 FIELD PROCEDURE NAMES 15 J01 START IF EXTRA OUTPUT DESIRED B ON FOR PUNCHED AUTOCODER D ON FOR PRINTED LISTING AND PRESS START IF NO EXTRA OUTPUT DESIRED, PRESS START === end of printer output === /simh/Cobol/cobol_linux.ini-57> at cdp -n obj_deck.s CDP: creating new file: obj_deck.s HALT instruction, IS: 2830 (B 2063 'B) === Now autocode generated program printer output will be listed === 0101 JOB DISP-IBM-1401-SAMPLE 0102 CTL 4411 0103 ORG 400 0104 S01 DCW @HOLA COBOL@ 0105 S02 DCW @TEST@ 0106 LA10 EQU *&1 0107 A10 DCW #4 0108 ORG 0109 DCW @}@ 0110 INCLD ZDY 0111 INCLD ZZZ 0112 LTORG 0113 LTORGX EQU *&1 0114 ORG 87 0115 X1 DCW #03 0116 DC #02 0117 X2 DCW #03 0118 DC #02 0119 X3 DCW #03 0120 ORG LTORGX 0121 A05 DCW 00000 0122 SHR DCW #20 0123 ACM DC #20 0124 GNN DCW #20 0125 DC #20 0126 CNR DCW #05 0127 CNT DCW #03 0128 A0Q DCW @0@ 0129 A0R DCW @@@ 0130 A0K DCW @ @ 0131 A0J DCW @9@ 0132 DCW #15 0133 DA1 DC #50 0134 OVRLAY EQU *&1 0135 MVEOVR BAV *&1 * START. * DISPLAY @HOLA COBOL@. * * MOVE @TEST@ TO FIELD. * * DISPLAY FIELD. * * STOP RUN. * 0136 STARTS EQU *&1 0137 J01 EQU *&1 0138 B ZDY 0139 DCW 001 0140 DCW 004 0141 DCW 001 0142 DCW S01 0143 DCW @0@ 0144 DCW 010 0145 MLC S02,A10 0146 B ZDY 0147 DCW 001 0148 DCW 004 0149 DCW 001 0150 DCW A10 0151 DCW @0@ 0152 DCW 004 0153 L02005 H 0154 B L02005 0155 END STARTS IF EXTRA OUTPUT DESIRED B ON FOR PUNCHED AUTOCODER D ON FOR PRINTED LISTING AND PRESS START IF NO EXTRA OUTPUT DESIRED, PRESS START === end of printer output === Goodbye /simh/Cobol #アセンブリ言語のソースができました。アセンブルして実行します。
/simh/Cobol # i1401 autocoder_linux.ini IBM 1401 simulator V4.0-0 Current git commit id: 9e719822 /simh/Cobol/autocoder_linux.ini-7> at mt1 Autocoder.cobol.tap Tape Image 'Autocoder.cobol.tap' scanned as SIMH format. contains 474744 bytes of tape data (5312 records, 2 tapemarks) A potentially unreasonable number of record sizes(37) vs tape marks (2) have been found The tape format (SIMH) might not be correct for the 'Autocoder.cobol.tap' tape image /simh/Cobol/autocoder_linux.ini-9> at mt3 -n scratch.mt3 MT: creating new file: scratch.mt3 /simh/Cobol/autocoder_linux.ini-10> at mt4 -n scratch.mt4 MT: creating new file: scratch.mt4 /simh/Cobol/autocoder_linux.ini-11> at mt5 -n scratch.mt5 MT: creating new file: scratch.mt5 /simh/Cobol/autocoder_linux.ini-12> at mt6 -n scratch.mt6 MT: creating new file: scratch.mt6 /simh/Cobol/autocoder_linux.ini-15> at cdp -n obj_deck.crd CDP: creating new file: obj_deck.crd HALT instruction, IS: 448 (B 593 'F) SWITCH TO 1410 MODE, RESET START HALT instruction, IS: 540 (DCW @J16365 @) === Now autocode assembly printer output will be listed === JOB DISP-IBM-1401-SAMPLE PASS 3 COMPLETED UNREFERENCED LABELS A0R 1144 SHR 1074 (省略) DISP-IBM-1401-SAMPLE PAGE 1 SEQ PG LIN LABEL OP OPERANDS SFX CT LOCN INSTRUCTION TYPE CARD 101 1 01 000 JOB DISP-IBM-1401-SAMPLE 102 1 02 CTL 4411 103 1 03 ORG 400 0400 104 1 04 S01 DCW @HOLA COBOL@ 10 0409 4 105 1 05 S02 DCW @TEST@ 4 0413 4 106 1 06 LA10 EQU *&1 0414 107 1 07 A10 DCW #4 4 0417 4 108 1 08 ORG 0418 109 1 09 DCW @}@ 1 0418 4 110 1 10 INCLD ZDY MACRO 111 1 11 INCLD ZZZ MACRO 112 1 12 ORG 0419 113 ZDY SBR DSYSBR STORE ADDR OF PARAMETER AREA 4 0419 H 930 GEN 4 114 MLC DSYSBR,X2 PICK UP PARAMETERS 7 0423 M 930 094 GEN 4 (省略) 276 1 54 B L02005 4 1265 B S64 34 277 1 55 END STARTS / S17 080 35 END OF ASSEMBLY IF EXTRA OUTPUT DESIRED, SET SENSE SWITCH F ON, AND B ON FOR CONDENSED CARDS C ON FOR LOADABLE TAPE 6 D ON FOR LISTING TAPE 3 E ON TO SUPPRESS LISTING G ON FOR NEW SOURCE DECK AND PRESS START IF NO EXTRA OUTPUT DESIRED, PRESS START END OF JOB INPUT FOR RE-ASSEMBLY ON TAPE UNIT 4 === end of printer output === /simh/Cobol/autocoder_linux.ini-56> at mt3 -n scratch.mt3 MT: creating new file: scratch.mt3 /simh/Cobol/autocoder_linux.ini-57> at mt4 -n scratch.mt4 MT: creating new file: scratch.mt4 /simh/Cobol/autocoder_linux.ini-58> at mt5 -n scratch.mt5 MT: creating new file: scratch.mt5 /simh/Cobol/autocoder_linux.ini-59> at mt6 -n scratch.mt6 MT: creating new file: scratch.mt6 /simh/Cobol/autocoder_linux.ini-62> at cdp -n out_deck.crd CDP: creating new file: out_deck.crd HOLA COBOL TEST HALT instruction, IS: 1265 (B 1264) Goodbye /simh/Cobol #
- 投稿日:2019-07-04T15:01:42+09:00
AWS SDK for C++のサンプルをVisual Studio Codeでデバッグする
C++でAWSのサービスを使う必要が出てきたのですが、幸いにも各言語ごとのサンプルコードが提供されているので、お勉強のために以前作った開発環境でデバッグしてみました。
はじめに
以前の記事と同様ですが
注意 Docker上でgdbを使うためにセキュリティレベルを下げる設定を追加しています。外部に公開される環境では用いないようにしてください。
作業概要
Visual Studio CodeのRemote ContainersでC++開発環境構築 - Qiita で作成したプロジェクトをベースに環境を作っていきます
変更するのは以下2点です。
DockerfileにAWS SDKのビルド設定を追加するdocker-compose.ymlのvolumesを変更する
- マウントするパスの変更
- AWSにアクセスするために
$HOME/.awsをマウントプロジェクトをダウンロード
# ベースとなるプロジェクトをクローン git clone https://github.com/dbgso/vscode-cpp-devcontainer.git vscode-remote-cpp-aws-sdkaws # サンプルソースをダウンロード git clone https://github.com/awsdocs/aws-doc-sdk-examples.git vscode-remote-cpp-aws-sdkaws/data/aws-doc-sdk-examples # Visual Studio Codeで開く code vscode-remote-cpp-aws-sdkawsここから、必要な設定を追加していきます
差分については https://github.com/dbgso/vscode-cpp-devcontainer/commit/c17e6ac33cc5512385ef3b1583d83c796bf10f9e をみてもらっても同じ内容です
Dockerfile修正
変更内容は以下です。
AWS SDK for CPPの依存パッケージをインストールしてビルドしています。Dockerfile.diffapt-get install -y git build-essential cmake clang libssl-dev && \ apt-get install -y cpputest libsqlite3-dev clang-format gdb +# AWS dependency +RUN apt-get install -y libcurl4-openssl-dev libssl-dev uuid-dev zlib1g-dev libpulse-dev + +RUN git clone https://github.com/aws/aws-sdk-cpp.git --depth 1 /tmp/aws-sdk-cpp +RUN cd /tmp/aws-sdk-cpp && cmake -DBUILD_ONLY="s3" && make && make install参考
Setting Up the AWS SDK for C++ - AWS SDK for C++
DockerとMinioでAWS SDK for C++の開発環境を構築する - Qiitadocker-compose.yml修正
現状の
devcontainer.jsonの設定ではworkingFolderを/dataとしているので、/dataにソースのルートを持ってくる必要があります。
ですので、docker-compose.ymlのvolumesでマウントするディレクトリを変更します。
Dockerfileでも-DBUILD_ONLY="s3"としたので今回はs3のサンプルを試していきます。
マウントするパスは/aws-doc-sdk-examples/cpp/example_code/s3/となります。(あるいはdevcontainer.jsonを変更して"workspaceFolder": "/data/aws-doc-sdk-examples/cpp/example_code/s3/"としても良いです。こっちの方が見通しが良いかな?)version: '3.3' services: cpp: build: . volumes: - - ../data:/data + - ../data/aws-doc-sdk-examples/cpp/example_code/s3/:/data + - $HOME/.aws/:/root/.aws working_dir: /data tty: true # to use gdb cap_add: - SYS_PTRACE security_opt: - seccomp:unconfined起動
起動方法は前回の記事と変わりません。
の
Reopen in Containerを選択するか、コマンドパレットからRemote-Containers: Reopen Folder in Containerを実行します。起動するとAWS SDKのビルドが始まりますが、結構長いのでしばらく待機します。(PCのスペックにもよりますが、5分〜15分程度?かかります)
ビルド
コマンドパレットから
CMake: buildを実行します。
No CMake kits are availableと聞かれたらDo not use a kitで良さそうです。(前回は選択してましたが、結局CMakeにお任せしていたので意味なかった?です)こんな感じでログがつらつら流れれば成功です。
[cmake] The C compiler identification is GNU 7.4.0 [cmake] The CXX compiler identification is GNU 7.4.0 [cmake] Check for working C compiler: /usr/bin/cc [cmake] Check for working C compiler: /usr/bin/cc -- works [cmake] Detecting C compiler ABI info [cmake] Detecting C compiler ABI info - done [cmake] Detecting C compile features [cmake] Detecting C compile features - done [cmake] Check for working CXX compiler: /usr/bin/c++ [cmake] Check for working CXX compiler: /usr/bin/c++ -- works [cmake] Detecting CXX compiler ABI info [cmake] Detecting CXX compiler ABI info - done [cmake] Detecting CXX compile features [cmake] Detecting CXX compile features - done [cmake] Found AWS SDK for C++, Version: 1.7.138, Install Root:/usr/local, Platform Prefix:, Platform Dependent Libraries: pthread;crypto;ssl;z;curl [cmake] Components specified for AWSSDK: s3 [cmake] Try finding aws-cpp-sdk-core [cmake] Found aws-cpp-sdk-core [cmake] Try finding aws-cpp-sdk-s3 [cmake] Found aws-cpp-sdk-s3 [cmake] Configuring done [cmake] Generating done [build] Starting build [proc] Executing command: /usr/bin/cmake --build /data/build --config Debug --target list_buckets -- -j 6 [build] Scanning dependencies of target list_buckets [build] [ 50%] Building CXX object CMakeFiles/list_buckets.dir/list_buckets.cpp.o [build] [100%] Linking CXX executable list_buckets [build] [100%] Built target list_buckets [build] Build finished with exit code 0実行とブレークポイント
バケット一覧取得
一番お手軽そうな
list_buckets.cppでバケットのリストを取得してみます。まず、確認用に適当なバケットを作ってファイルを置いておきます(
これもC++でやればいいんですが、記事にするのが面倒臭い)$ aws s3 mb s3://cppbuckettest make_bucket: cppbuckettest $ echo hello > world.txt $ aws s3 cp world.txt s3://cppbuckettest upload: ./world.txt to s3://cppbuckettest/world.txt $ aws s3 ls s3://cppbuckettest/ 2019-07-04 13:06:47 6 world.txtブレークポイントを設定してステップ実行していくと、ちゃんと
cppbuckettestの存在を確認できました。オブジェクトの取得
せっかくファイルをアップロードしたので、バケットのファイル一覧を取得します。
サンプルのソースはlist_objects.cppです。このファイルはコマンドライン引数にバケット名を渡して、そのバケットのファイル名一覧を取得しているみたいです。
ここで、ちょっとハマりました。
コマンドライン引数はどこに渡すの?って思ったんですが、普通にlaunch.jsonの設定に書けばよかったです。
launch.jsonを開いて、C/C++: (gdb) Launchを選択して、テンプレートを生成します。以下のように、
programに実行ファイル、argsにコマンドライン引数を入れればOKです。{ "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", - "program": "enter program name, for example ${workspaceFolder}/a.out", + "program": "${workspaceFolder}/build/list_objects", - "args": [], + "args": ["cppbuckettest"], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ] }
F5キーで実行しますちゃんとブレークして、該当のバケット情報が取れています。
コンソールにも正しく表示されましたObjects in S3 bucket: cppbuckettest * world.txt備考
.awsディレクトリのマウント漏れ
ちなみに、
.awsディレクトリをマウントし忘れると以下のように接続できなくて怒られるので注意しましょうListBuckets error: - Unable to connect to endpoint [1] + Done /usr/bin/gdb --interpreter=mi --tty=${DbgTerm} 0</tmp/Microsoft-MIEngine-In-2xmmhqio.v6u 1>/tmp/Microsoft-MIEngine-Out-l2adjy68.7nbCMake拡張機能を使ってのコマンドライン引数
本文では引数指定ができないと書いたのですが、すみません、できました。
ただ、使い勝手的にはlaunch.jsonに書いてしまうのが良いと思うので、参考までに記録しておきます。方法はVisual Studio Code側の設定に引数を設定してしまう方法です。
Preferences: Open Workspace SettingsからWorkspaceごとの設定を開き、以下のようにargsに設定します。setting.json{ "cmake.debugConfig": { "args": [ "bucket_name" ] } }あとは、通常通り
Debugボタンを押せば引数付きでデバッグできますただ、おそらく設定は一つしかできないです。
Workspaceに設定するのでそれでも良さそうですが、使い勝手は悪そう。
ちなみにシステム側の設定にもできてしまいますが普通しませんよね。
おとなしく、launch.jsonが良いかなと思いました。お手軽実行の時はすごく楽で良いんですが参考 Passing command line arguments to a debug target · Issue #121 · vector-of-bool/vscode-cmake-tools
参考
Setting Up the AWS SDK for C++ - AWS SDK for C++
DockerとMinioでAWS SDK for C++の開発環境を構築する - Qiita
Passing command line arguments to a debug target · Issue #121 · vector-of-bool/vscode-cmake-tools
- 投稿日:2019-07-04T14:12:30+09:00
エディターがセーブできない。localhost が読み込めない。→dockerのメモリ足りてる?
- 投稿日:2019-07-04T10:05:21+09:00
【連載第2回】Kotlin と SpringBoot を利用して、TDDスタイルで「お誕生日会支援ツール」を作ってみる 〜園児マスタ管理①〜
今回の内容
- 前回の続きです。
- 今回は「園児登録」を作成していきます。所属クラスやアレルギー等、付加情報との紐づけは次回。
TODOリスト
- DB準備
- 園児マスタテーブルを作成
- 園児登録画面の表示
データベース起動
Docker起動
MySQLはDockerでサクッと用意してしまいます。
データ部を外出しにして永続化しておきますので、-v オプションの保存先パスは適宜修正して下さい。docker run --name sample-mysql -e MYSQL_ROOT_PASSWORD=password -v /Users/hoge/docker/mysql/db:/var/lib/mysql -p 3306:3306 -d mysql:5.7一度作成した後は、
docker ps -aでIDを調べて、docker start XXXXXXXXで起動できます。データベース(スキーマ)作成
アプリケーション用のデータベースを定義しておきます。
docker exec -it sample-mysql bash mysql -uroot -p # パスワードは、docker起動時に指定した"password" create database birthdaycalendar; #DB名は任意プロジェクトのプロパティファイル設定
プロジェクトの
/src/resources/application.propertiesファイルに、MySQL接続設定を記述します。/src/resources/application.propertiesspring.datasource.url=jdbc:mysql://127.0.0.1:3306/birthdaycalendar spring.datasource.username=root spring.datasource.password=password spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver spring.jpa.database=MYSQL spring.jpa.hibernate.ddl-auto=update起動確認
IntelliJ IDEA のメニューから
[表示]->[ツール・ウィンドウ]->[Gradle]を選択し、Gradleタスクを表示します。
表示されたタスク一覧から、[Tasks]->[application]->[bootRun]を選択して、プロジェクトを起動し、http://localhost:8080 にアクセスできればOKです。
(まだ何もプログラムを書いていないので、404エラーが出ると思いますが・・・)園児マスタを作成
園児情報を格納するマスタテーブルを作成します。
「テーブルを作成」と書きましたが、JPAの場合、Entityクラスに対応するテーブルが存在しない場合、自動で作成してくれますので、今回はひとまずEntityを作成します。園児Entity
/src/com/example/birthdaymanager/domain/child/Child.ktpackage com.example.birthdaymanager.domain.child import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.LastModifiedDate import org.springframework.data.jpa.domain.support.AuditingEntityListener import java.util.Date import javax.persistence.* @Entity @EntityListeners(AuditingEntityListener::class) class Child { @Id @GeneratedValue var id: Long? = null var familyName: String? = null var middleName: String? = null // 外国籍の園児さんで利用することがあります。 var firstName: String? = null var birthday: Date? = null var validSince: Date? = null var validThru: Date? = null @CreatedDate @Temporal(TemporalType.TIMESTAMP) @Column(nullable = false, updatable = false) var createdAt: Date? = null @LastModifiedDate @Temporal(TemporalType.TIMESTAMP) @Column(nullable = false, updatable = false) var updatedAt: Date? = null }アプリケーションクラスに、以下のアノテーションを追加します。
Entityで宣言した、@CreatedDate/@LastModifiedDateを有効にします。/src/com/example/birthdaymanager/BirthdaycalendarApplication.kt(中略) @SpringBootApplication @EnableJpaAuditing // ここを追記 class BirthdaycalendarApplication (以下略)園児リポジトリ作成
園児Entityのロード/ストアを担当する、園児リポジトリを作成します。
JpaRepository<T, ID>を継承したインタフェースを定義すると、対象Entityに対する標準的な操作が可能なリポジトリが自動生成されます。/src/com/example/birthdaymanager/domain/child/ChildRepository.ktpackage com.example.birthdaymanager.domain.child import org.springframework.data.jpa.repository.JpaRepository interface ChildRepository : JpaRepository<Child, Long>園児サービスの作成
ビジネスロジックを実装する、サービス層を作成します。
各ビジネスロジックは、今後の実装に合わせて追加していきますので、現時点ではひとまず雛形の形になります。/src/com/example/birthdaymanager/domain/child/ChildService.ktpackage com.example.birthdaymanager.domain.child import org.springframework.stereotype.Service @Service class ChildService(private val childRepository: ChildRepository) { }園児コントローラの作成
ここまでは暗黙機能のみで実装してきたため、テストコードを割愛しておりましたが、ここからは少しずつTDDのリズムで開発を進めていくようにしていきます。
園児コントローラテスト(1) 〜テスト失敗〜
園児登録画面のコントローラ実装に先立ち、テストコードを書いてみます。
URL:[GET]/children/new/src/com/example/birthdaymanager/presentation/child/ChildControllerTest.ktpackage com.example.birthdaymanager.presentation.child import com.example.birthdaymanager.domain.child.ChildService import com.nhaarman.mockitokotlin2.mock import org.junit.Assert.* import org.junit.Test import org.junit.runner.RunWith import org.springframework.test.context.junit4.SpringJUnit4ClassRunner @RunWith(SpringJUnit4ClassRunner::class) class ChildControllerTest { init { } fun setup() { } @Test fun new() { val service = mock<ChildService>() val childController = ChildController(service) val actual = childController.new() assertEquals("child/new", actual) } }コンパイルエラーにならない程度にControllerクラスを作成し、空の実装としておきます。
/src/com/example/birthdaymanager/presentation/child/ChildController.ktpackage com.example.birthdaymanager.presentation.child import com.example.birthdaymanager.domain.child.ChildService import org.springframework.stereotype.Controller import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping @Controller @RequestMapping("/children") class ChildController( private val childService: ChildService ) { @GetMapping("new") fun new():String { return "" } }テスト結果がエラーになることを確認します。
園児コントローラテスト(2) 〜仮実装〜
テストがエラーになることを確認できましたら、テストをパスするための最短の実装(”仮実装”)を追加します。
ただし、今回は分岐パターン等もいまのところありませんので、いわゆる"明白な実装"になります。/src/com/example/birthdaymanager/presentation/child/ChildController.kt(前略) @Controller @RequestMapping("/children") class ChildController( private val childService: ChildService ) { @GetMapping("new") fun new():String { return "children/new" // ここを変更 } }今度はテストがパスすることが確認できると思います。
今回は今のところ分岐等が存在しない処理のため、テストケースも以上になりますが、今後もテスト作成 -> テスト失敗 -> 仮実装 -> テストパス -> テストケース追加・リファクタリングの流れを繰り返しながら進めていきます。園児登録Viewの作成
園児登録画面の雛形を作ってみます。
関連ライブラリの用意
画面用コンポーネントとして、以下のライブラリを使用します。
/src/main/resources/static/以下に関連ファイルを展開して下さい。園児登録View
ここでは動作確認程度でOKです。
JS/CSSの読み込み等、各画面共通の部分は、後ほど共通のレイアウトファイルに移します。サーバーを起動(bootRun)し、http://localhost:8080/children/new にアクセスして表示を確認して下さい。
/src/main/resources/templates/children/new.html<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8" /> <title>園児登録</title> <link rel="stylesheet" href="/css/bootstrap.min.css" /> <link rel="stylesheet" href="/css/mdb.css" /> <link rel="stylesheet" href="/css/style.css" /> <link rel="stylesheet" href="/css/bootstrap-datepicker.min.css" /> </head> <body> <div class="container"> <h1>園児登録</h1> <form th:action="@{/children}" th:method="post"> <div class="md-form"> <label class="control-label">性</label> <input class="form-control" type="text" name="familyName" /> </div> <div class="md-form"> <label class="control-label">名</label> <input class="form-control" type="text" name="firstName" /> </div> <div class="md-form"> <label class="control-label">ミドルネーム</label> <input class="form-control" type="text" name="middleName" /> </div> <div class="row"> <div class="col-md-4"> <div class="md-form"> <label class="control-label">誕生日</label> <input class="form-control datepicker" type="text" name="birthday" /> </div> </div> <div class="col-md-4"> <div class="md-form"> <label class="control-label">入園日</label> <input class="form-control datepicker" type="text" name="validSince" /> </div> </div> <div class="col-md-4"> <div class="md-form"> <label class="control-label">退園日</label> <input class="form-control datepicker" type="text" name="validThru" /> </div> </div> </div> <button class="btn btn-primary" type="submit">作成</button> </form> </div> <script src="/js/jquery-3.4.1.min.js"></script> <script src="/js/popper.min.js"></script> <script src="/js/bootstrap.js"></script> <script src="/js/mdb.js"></script> <script src="/js/bootstrap-datepicker.min.js"></script> <script src="/js/bootstrap-datepicker.ja.min.js"></script> <script type="text/javascript"> $('.datepicker').datepicker({ language: 'ja', autoclose: true }); </script> </body> </html>長くなってきたので今回はこの辺りで。
次回はいよいよテストもゴリゴリ書きつつ、園児登録処理や編集画面などを作り進めながら、コードの整理をしていきます。TDDよもやま話①
TDD実践の参考になれば。
TDD実装時の流れ/よく使うショートカット
IntelliJ IDEA が持つショートカットを駆使しながら、例えば以下のような手順でサクサク進めることができるようになります。IntelliJ IDEAに限らず、IDEを利用する場合、IDEに備わっているコード補完機能等をフルに活用するのがポイントです。
Cmd+Nでテストクラスを作成(※まだクラスが存在しない場合)Ctrl+Enterでテストコードを書く(※対象クラス/メソッドが存在しない場合、この時点ではコンパイルエラーになるはず)- エラー箇所で
Ctrl+Enterを押し、コード補完からテスト対象クラス/メソッドを作成する。(いちいち手作業で作成するより楽です)- テストクラス側で
Ctrl+Shift+Rでテスト実行し、テスト失敗を確認- テストクラス側で
Cmd+Shift+Tでテスト対象クラスに移動し、実装を追加する。Ctrl+Rでテスト再実行し、テストが通ることを確認。- テストコードを追加し、上記4以降の手順を繰り返す。
- 投稿日:2019-07-04T09:45:04+09:00
bridge(default,user-defined),hostネットワークドライバのコンテナ間通信の方法について調べた
コンテナ間通信の方法について調べた時のメモです。
他のホストのコンテナへの通信ではなく、同じホストでのコンテナでの通信に関してです。
そのため、対象のネットワークは「bridge」及び「host」のみです。TL:DR
- host ネットワークの場合には localhost:port で接続出来る
- bridge ネットワークについてはそもそも「default bridge」と「user-defined bridge」の2つがある
- 「default bridge」の場合、
--linkオプションもしくは IP アドレスを指定して接続する必要がある- 「user-defined bridge」の場合、コンテナ名で名前解決が出来る
--linkオプションは将来的に廃止される可能性があるので「user-defined bridge」の利用が推奨されているDocker のネットワークドライバについて
Docker ではいくつかのネットワークドライバを提供しています
- bridge
- host
- overlay
- macvlan
- none
- Network plugins
今回の確認対象である bridge 及び host の内容について以前確認した記事を参照下さい。
Docker の bridge と host ネットワークについて勉強する
なお、それぞれの使い分けは以下のように記載があります。
Network driver summary
User-defined bridge networks are best when you need multiple containers to communicate on the same Docker host.
Host networks are best when the network stack should not be isolated from the Docker host, but you want other aspects of the container to be isolated.
Overlay networks are best when you need containers running on different Docker hosts to communicate, or when multiple applications work together using swarm services.
Macvlan networks are best when you are migrating from a VM setup or need your containers to look like physical hosts on your network, each with a unique MAC address.
Third-party network plugins allow you to integrate Docker with specialized network stacks.
bridge については同じ Docker ホストで複数のコンテナが通信をする時に最適と書いてあります。
host はコンテナの隔離(isolation)は行いたいが、ネットワークスタックの隔離をしたくない時に最適と書いてあります。なお、あとで出てきますが、bridge については「default bridge」ではなく、「user-defined bridge」と書いてあることからもなるべく user-defined な bridge を使って欲しいんだろうなという気持ちが汲み取れました。
bridge の 「default bridge」と「user-defined bridge」って何?
以下に詳細がありますが、記載します。
bridge はデフォルトのネットワークドライバであり、
docker runの時に何も指定しない場合には bridge が選ばれます。
そしてこの場合、「default bridge」が利用されます。
具体的には以下のような構成となります。次に「user-defined bridge」ですが、
docker network createコマンドで作る事ができます。
また、docker runの時に上記を利用するように指定できます。
具体的には以下のようなコマンドです。$ docker network create -d bridge --subnet 10.0.0.0/24 my_bridge $ docker run -itd --name c2 --net my_bridge busybox sh $ docker run -itd --name c3 --net my_bridge --ip 10.0.0.254 busybox shこの場合、以下のようになります。
状況としては
- c1 は defautl bridge を使っている
- c2,c3 は user-defined bridge を使っている
と言えると思います。
色々調査するまでこれらにあまり違いと思っていたのですが結構違いがありました。「user-defind bridge」と「default beridge」の違いの詳細については以下に記載があります
Differences between user-defined bridges and the default bridge
- User-defined bridges provide better isolation and interoperability between containerized applications.
- User-defined bridges provide better isolation and interoperability between containerized applications.
- Containers can be attached and detached from user-defined networks on the fly.
- Each user-defined network creates a configurable bridge.
- Linked containers on the default bridge network share environment variables.
default bridge でコンテナ間通信を行う場合
書いてある通りですが、
--linkを使うか、IP アドレスを利用する方法のみとなっています。Containers on the default bridge network can only access each other by IP addresses, unless you use the --link option, which is considered legacy
なお、
--linkは legacy であり、user-defined bridge を使うことを推奨されています。Warning: The --link flag is a legacy feature of Docker. It may eventually be removed. Unless you absolutely need to continue using it, we recommend that you use user-defined networks to facilitate communication between two containers instead of using --link. One feature that user-defined networks do not support that you can do with --link is sharing environment variables between containers. However, you can use other mechanisms such as volumes to share environment variables between containers in a more controlled way.
user-defined bridge でコンテナ間通信を行う場合
user-defined bridge ではコンテナ名で名前解決が出来ます。
User-defined bridges provide automatic DNS resolution between containers.
On a user-defined bridge network, containers can resolve each other by name or alias.上記より、
--link指定は必要はなく、同じ user-defined bridge はコンテナ同士での通信が容易に出来ます。実際に試された記事がありましたので記載します
host ネットワークでコンテナ間通信を行う
host network を使う場合、ネットワークの隔離は行われていません。
Docker Reference Architecture: Designing Scalable, Portable Docker Container Networks
Host With the host driver, a container uses the networking stack of the host. There is no namespace separation, and all interfaces on the host can be used directly by the container
host network を使ってコンテナを2つ起動した場合、以下のようになります。
そのため、locahost で接続可能です。
# 8080 で expose するコンテナを host ネットワークで起動 $docker run -it --rm --net host -d tomcat:8.0 # host ネットワークでコンテナを起動して localhost で接続。 $docker run -it --rm --net host ubuntu /bin/bash #apt-get update #apt-get install curl -y #curl http://localhost:8080 ・・・ <div class="col20"> <div class="container"> <h4>Apache Software Foundation</h4> <ul> <li><a href="https://tomcat.apache.org/whoweare.html">Who We Are</a></li> <li><a href="https://tomcat.apache.org/heritage.html">Heritage</a></li> <li><a href="https://www.apache.org">Apache Home</a></li> <li><a href="https://tomcat.apache.org/resources.html">Resources</a></li> </ul> </div> </div> <br class="separator" /> </div> <p class="copyright">Copyright ©1999-2019 Apache Software Foundation. All Rights Reserved</p> </div> </body> </html>
- 投稿日:2019-07-04T07:34:27+09:00
Simh/i1401 with COBOL on docker(1)
Simh/i1401 with FortranIV on dockerではFortranIVをターゲットにしました。
Simhの実行イメージができれば、それを使って応用できます。
次はCOBOLのプログラムを実行してみます。
使うテープイメージはIBM 1401 COBOL e-mailsで紹介されている
i1401-Cobol-Generation.zipと
i1401-Cobol.zipを使用します。
最初にCOBOLコンパイラのテープイメージを作成します。i1401-Cobol-Generation.zipに含まれているCobol_Generation.iniはWindows向けですので、
Linux向けのものを用意します。Cobol_Generation_for_linux.ini; Generates Cobol.tap (cobol compiler tape) and ; autocode.cobol.tap (Autocode to assemble compiler output) SET CPU 16K set CPU NEWCONVERSIONS SET CDP BUSINESS SET LPT BUSINESS at mt1 adc00223_Cobol.mt1 at mt2 -n Cobol.tap at mt3 -n Extraction.tap Echo Echo *** Extract cobol compiler tape and extraction tape from PID Cobol echo *** distribution tape from IBM Echo boot mt1 Echo Echo *** Now process extraction tape to ... at mt1 Extraction.tap det mt2 det mt3 boot mt1 Echo Echo ... Print Cobol Phase Listings (Source code) echo at lpt -n Cobol_Source_Listing.txt go Echo Echo ... Punch Cobol Subrutines and Sample Program echo ; punch cards in staker4 (not in CDP device) at stkr4 -n Extaction_cards.crd go ; separate cards using identification numbers ! grep " 70001" Extaction_cards.crd > "Cobol_4k_subs.crd" ! grep " 70002" Extaction_cards.crd > "Cobol_4kp_subs.crd" ! grep " 70003" Extaction_cards.crd > "Cobol_Sample_Program.crd" det stkr4 !rm Extaction_cards.crd det lpt echo Echo *** Now Place Cobol Soubroutines in the Autocoder Library echo at mt1 Autocoder+IOCS.tap at mt6 -n Autocoder.cobol.tap at cdr Cobol_4kp_subs.crd set lpt default dep ssa 1 dep ssf 1 boot mt1 echo quitSimh実行用のDockerイメージを起動します。また、Cobol_Generation_for_linux.iniをコピーします。
C:\kazu>docker run -it kazu_simh:i1401 / # cd /simh /simh # wget http://ibm-1401.info/pictures/000COBOL/i1401-Cobol-Generation.zip Connecting to ibm-1401.info (45.40.183.1:80) i1401-Cobol-Generati 100% |****************************************************************| 1888k 0:00:00 ETA /simh # unzip i1401-Cobol-Generation.zip Archive: i1401-Cobol-Generation.zip creating: generation/ inflating: generation/adc00223_Cobol.mt1 inflating: generation/Autocoder+IOCS.tap inflating: generation/Autocoder.cobol.tap inflating: generation/Cobol.tap inflating: generation/Cobol_4kp_subs.crd inflating: generation/Cobol_4k_subs.crd inflating: generation/Cobol_Generation.ini inflating: generation/Cobol_Sample_Program.crd inflating: generation/Cobol_Source_Listing.txt inflating: generation/Extraction.tap inflating: generation/run Cobol Generation.bat /simh # cd generation/ /simh/generation # ls Autocoder+IOCS.tap Cobol_4k_subs.crd Cobol_Sample_Program.crd adc00223_Cobol.mt1 Autocoder.cobol.tap Cobol_4kp_subs.crd Cobol_Source_Listing.txt run Cobol Generation.bat Cobol.tap Cobol_Generation.ini Extraction.tap /simh/generation # cp ../Cobol_Generation_for_linux.ini .では、コンパイラのテープイメージを作成します。
/simh/generation # i1401 Cobol_Generation_for_linux.ini IBM 1401 simulator V4.0-0 Current git commit id: 9e719822 /simh/generation/Cobol_Generation_for_linux.ini-11> at mt1 adc00223_Cobol.mt1 Tape Image 'adc00223_Cobol.mt1' scanned as SIMH format. contains 4754130 bytes of tape data (3666 records, 7 tapemarks) A potentially unreasonable number of record sizes(171) vs tape marks (7) have been found The tape format (SIMH) might not be correct for the 'adc00223_Cobol.mt1' tape image /simh/generation/Cobol_Generation_for_linux.ini-12> at mt2 -n Cobol.tap MT: creating new file: Cobol.tap /simh/generation/Cobol_Generation_for_linux.ini-13> at mt3 -n Extraction.tap MT: creating new file: Extraction.tap *** Extract cobol compiler tape and extraction tape from PID Cobol *** distribution tape from IBM HALT instruction, IS: 3686 (B 3681) *** Now process extraction tape to ... HALT instruction, IS: 364 (SWM 723) ... Print Cobol Phase Listings (Source code) /simh/generation/Cobol_Generation_for_linux.ini-35> at lpt -n Cobol_Source_Listing.txt LPT: creating new file: Cobol_Source_Listing.txt HALT instruction, IS: 600 (B 697) ... Punch Cobol Subrutines and Sample Program /simh/generation/Cobol_Generation_for_linux.ini-43> at stkr4 -n Extaction_cards.crd STKR: creating new file: Extaction_cards.crd HALT instruction, IS: 709 (B 702) *** Now Place Cobol Soubroutines in the Autocoder Library /simh/generation/Cobol_Generation_for_linux.ini-60> at mt1 Autocoder+IOCS.tap Tape Image 'Autocoder+IOCS.tap' scanned as SIMH format. contains 426122 bytes of tape data (4197 records, 3 tapemarks) A potentially unreasonable number of record sizes(39) vs tape marks (3) have been found The tape format (SIMH) might not be correct for the 'Autocoder+IOCS.tap' tape image /simh/generation/Cobol_Generation_for_linux.ini-61> at mt6 -n Autocoder.cobol.tap MT: creating new file: Autocoder.cobol.tap 1401 AUTOCODER - LIBRARY CHANGES PAGE 1 (省略) 17 ZSPSV3 DCW #3 INDEX REGISTER 3 SAVED HERE 1401 AUTOCODER SYSTEM COPIED ON TAPE UNIT 6 HALT instruction, IS: 704 (B 1021) Goodbye /simh/generation #
- 投稿日:2019-07-04T00:40:30+09:00
GCP(GCE)でハマる「無料」の罠
三行で概要紹介
無料で使えるf1-microのGCEインスタンスでWebアプリ(コンテナ)のデプロイに失敗
ハマったポイントはgradleのdeamonの起動(が、終わらない)
原因はおそらくインスタンスのパワー不足用語の超ざっくり解説
- GCP: Google Cloud Platform
Googleが提供するクラウドサービス。競合はAWSとかAzureとか。
- GCE: Google Compute Engine
GCPのIaaS。VMインスタンス。AWSでいうEC2。
- GCS: Google Cloud Storage
GCPのオブジェクトストレージ。AWSでいうS3。
- Google Container Registry
GCPのDockerイメージのストレージ。AWSでいうAmazon Elastic Container Registry。背景
SpringBootで作った簡単なWebアプリを公開して、色んな端末で使いたい
→ でも、できれば金はかけずに手軽にやりたいな・・・
→ お、GCPの一番安いVMインスタンスは実質ずっと無料で使えるやん。これや!
GCPの無料枠(抜粋):https://cloud.google.com/free/docs/gcp-free-tier?hl=jaやったこと
せっかくGCPを使うのだから、アプリをコンテナ化してやってみた。
おおまかな手順は以下の通り。
1.アプリケーション開発。
2.アプリケーションのDockerイメージ作成。ローカルで動作確認。
3.GCPにアカウント登録。
4.ローカルのDockerイメージをGoogle Container Registryに登録。
5.登録したDockerイメージを紐付けてVMインスタンスを作成。
6.VMインスタンスを起動し、ブラウザでアプリが立ち上がっていることを確認。※ 4~6については、下記の参考で紹介している記事を参照。
参考:GCEにSpringBootアプリケーションをデプロイする方法
Google Container Engine (GKE) 使えやってツッコミも飛んできそうですが、
手軽にパパッとやるなら大きく2つの方法があるみたい。他にもあれば教えてください。1.GCSのバケットにjarを配置する方法
公式ドキュメントを参照。英語やけど。
Run a Spring Boot application on Google Compute Engine2.VMインスタンス作成時にDockerイメージを紐づける方法
DockerイメージはGoogle Container RegistryやDockerHubなどから指定する。
Google Container Registryは有料だけど、数円レベルなので許容した。
公式ドキュメントも大変分かりやすかったが、こちらがまとまっていて一番参考になった。
dockerイメージを GCE で起動する方法
↑ ローカルからGoogle Container Registryへアップするところから説明してくれています。そして、ハマる
前置きが長くなりました。
私は当初の思惑通り、一番安い(というか無料の)f1-micro(vCPU x 1、メモリ 0.6 GB)インスタンスを作成していたのですが、アプリが立ち上がらなくてハマりました。
※ GCPの初期登録時に一年間使える3万円くらいのクレジットをもらえましたが、一年後以降のことも考えて無料のインスタンスを選択しました。ログをみてる感じは正常そうなんですが、一向にGradleのデーモンが立ち上がってくれません。
何度か再起動させてみたり、インスタンス作り直したり、2日待ってみたりしたが、結局ここから進むことはなく・・・・・・で、どうしたか
すみません、結局、根本的な原因は分かりませんでした。
ただ、以下の2点から、単純にf1-microインスタンスのパワー不足としか思えませんでした。
- f1-microインスタンスのCPU利用率が常に100%近く(下記のグラフ参照)
- 比較用にn1-standard-2(vCPU x 2、メモリ 7.5 GB)を作成したが、同様の問題は発生せず。
(※ブラウザでもアプリケーションが動いていることを確認できました。)
※ instance-3はn1-standard-2インスタンスです。見やすさのためグラフを非表示にしてます。所感
SpringBootの簡単なアプリケーションですら、起動できないのは予想外でした。
「インスタンス「f1micro1cpu-614mb」は過剰に使われています。次のマシンタイプへの切り替えを検討してください: g1-small(vCPU x 1、メモリ 1.7 GB)。」なんてメッセージすら届きました。
無料にこだわったばかりにかなり多くの時間を費やしてしまいました。素直にJarでやれば良かったです。
とはいえ、初めてGCPだけでなくDockerも初めて触ったのでいい経験にはなりました。
かなりレアなケースかと思いますが、同じようにハマった方の参考になれば幸いです。










