20190704のdockerに関する記事は8件です。

【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を用いてデータベースを作成していました。

個人的に苦しんだエラー特集

以下の記事を参考にしてDockerの環境を構築しました。

目的(機械学習のついでに、ローカルを汚さないようにするために...など)が果たせればOKと判断して雰囲気でDocker使ってたので、今回苦労しました(・・;) 夏休みあたりにちゃんとDocker勉強します?

Dockerでマイグレーションが作成できない

.envのDB_HOSTをデフォルト設定から変更する必要がある。docker-compose.ymlでserviceとして定義した名前を使用する。

phpMyAdminにログインできない

環境変数内(.env)のユーザーネーム、パスワード、サーバ名、全て同じものを使用してログインを試みたのに何度試しても失敗。
もう一度コンテナを作り直したら解決した。原因不明?
このエラー解消に恐ろしく時間取られたのが本当に悔しい...!

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Simh/i1401 with COBOL on docker(2)

Simh/i1401 with COBOL on docker(1)ではCOBOLコンパイラのテープイメージを作成しました。
これを使ってCOBOLプログラムを実行します。
cobol.iniはWindows用ですので、Linux用を用意します。

cobol_linux.ini
SET 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.ini
SET 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 #
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS SDK for C++のサンプルをVisual Studio Codeでデバッグする

C++でAWSのサービスを使う必要が出てきたのですが、幸いにも各言語ごとのサンプルコードが提供されているので、お勉強のために以前作った開発環境でデバッグしてみました。

はじめに

以前の記事と同様ですが

注意 Docker上でgdbを使うためにセキュリティレベルを下げる設定を追加しています。外部に公開される環境では用いないようにしてください。

作業概要

Visual Studio CodeのRemote ContainersでC++開発環境構築 - Qiita で作成したプロジェクトをベースに環境を作っていきます

変更するのは以下2点です。

  1. DockerfileにAWS SDKのビルド設定を追加する
  2. 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.diff
    apt-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++の開発環境を構築する - Qiita

docker-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

起動

起動方法は前回の記事と変わりません。

reopenincontainer

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の存在を確認できました。

alt

オブジェクトの取得

せっかくファイルをアップロードしたので、バケットのファイル一覧を取得します。
サンプルのソースは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キーで実行します

alt

ちゃんとブレークして、該当のバケット情報が取れています。
コンソールにも正しく表示されました

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.7nb

CMake拡張機能を使ってのコマンドライン引数

本文では引数指定ができないと書いたのですが、すみません、できました。
ただ、使い勝手的にはlaunch.jsonに書いてしまうのが良いと思うので、参考までに記録しておきます。

方法はVisual Studio Code側の設定に引数を設定してしまう方法です。

Preferences: Open Workspace SettingsからWorkspaceごとの設定を開き、以下のようにargsに設定します。

setting.json
{    
    "cmake.debugConfig": {
        "args": [
            "bucket_name"
        ]
    }
}

あとは、通常通りDebugボタンを押せば引数付きでデバッグできます

alt

ただ、おそらく設定は一つしかできないです。
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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エディターがセーブできない。localhost が読み込めない。→dockerのメモリ足りてる?

・dockerを使っている
・エディターがセーブできなくて何度も npm start をしている
・localhost が読み込めない

こんなお悩み、dockerのメモリを上げることで解決するかもしれません。

やり方
1.dockerを一旦止める
fullsizeoutput_9.jpeg
2.Preferencesをクリック

fullsizeoutput_8.jpeg
3.ここのMemory, Swapをあげてみる

解決を願います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【連載第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.properties
spring.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.kt
package 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.kt
package com.example.birthdaymanager.domain.child

import org.springframework.data.jpa.repository.JpaRepository

interface ChildRepository : JpaRepository<Child, Long>

園児サービスの作成

ビジネスロジックを実装する、サービス層を作成します。
各ビジネスロジックは、今後の実装に合わせて追加していきますので、現時点ではひとまず雛形の形になります。

/src/com/example/birthdaymanager/domain/child/ChildService.kt
package 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.kt
package 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.kt
package 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に備わっているコード補完機能等をフルに活用するのがポイントです。

  1. Cmd+Nでテストクラスを作成(※まだクラスが存在しない場合)
  2. Ctrl+Enterでテストコードを書く(※対象クラス/メソッドが存在しない場合、この時点ではコンパイルエラーになるはず)
  3. エラー箇所でCtrl+Enterを押し、コード補完からテスト対象クラス/メソッドを作成する。(いちいち手作業で作成するより楽です)
  4. テストクラス側でCtrl+Shift+Rでテスト実行し、テスト失敗を確認
  5. テストクラス側でCmd+Shift+Tでテスト対象クラスに移動し、実装を追加する。
  6. Ctrl+Rでテスト再実行し、テストが通ることを確認。
  7. テストコードを追加し、上記4以降の手順を繰り返す。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 ではいくつかのネットワークドライバを提供しています

Network drivers

  • bridge
  • host
  • overlay
  • macvlan
  • none
  • Network plugins

今回の確認対象である bridge 及び host の内容について以前確認した記事を参照下さい。

Docker の bridge と host ネットワークについて勉強する

なお、それぞれの使い分けは以下のように記載があります。

Network driver summary

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」って何?

以下に詳細がありますが、記載します。

Use bridge networks

bridge はデフォルトのネットワークドライバであり、docker runの時に何も指定しない場合には bridge が選ばれます。
そしてこの場合、「default bridge」が利用されます。
具体的には以下のような構成となります。

bridge-driver.png

次に「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

この場合、以下のようになります。

bridge2.png

状況としては

  • 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 アドレスを利用する方法のみとなっています。

https://docs.docker.com/network/bridge/#differences-between-user-defined-bridges-and-the-default-bridge

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 を使うことを推奨されています。

Legacy container links

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 ではコンテナ名で名前解決が出来ます。

https://docs.docker.com/network/bridge/#differences-between-user-defined-bridges-and-the-default-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つ起動した場合、以下のようになります。

host-driver.png

そのため、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 &copy;1999-2019 Apache Software Foundation.  All Rights Reserved</p>
        </div>
    </body>

</html>

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
quit

Simh実行用の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 #
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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インスタンスは実質ずっと無料で使えるやん。これや!
gce_detail.png
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 Engine

2.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のデーモンが立ち上がってくれません。

log.png
何度か再起動させてみたり、インスタンス作り直したり、2日待ってみたりしたが、結局ここから進むことはなく・・・

・・・で、どうしたか

すみません、結局、根本的な原因は分かりませんでした。

ただ、以下の2点から、単純にf1-microインスタンスのパワー不足としか思えませんでした。
 - f1-microインスタンスのCPU利用率が常に100%近く(下記のグラフ参照)
 - 比較用にn1-standard-2(vCPU x 2、メモリ 7.5 GB)を作成したが、同様の問題は発生せず。
 (※ブラウザでもアプリケーションが動いていることを確認できました。)

cpu_log.png
※ instance-3はn1-standard-2インスタンスです。見やすさのためグラフを非表示にしてます。

所感

SpringBootの簡単なアプリケーションですら、起動できないのは予想外でした。
「インスタンス「f1micro1cpu-614mb」は過剰に使われています。次のマシンタイプへの切り替えを検討してください: g1-small(vCPU x 1、メモリ 1.7 GB)。」なんてメッセージすら届きました。
無料にこだわったばかりにかなり多くの時間を費やしてしまいました。素直にJarでやれば良かったです。
とはいえ、初めてGCPだけでなくDockerも初めて触ったのでいい経験にはなりました。
かなりレアなケースかと思いますが、同じようにハマった方の参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む