- 投稿日:2019-06-27T23:35:49+09:00
EC2の削除保護を無視してterminatedなる状況を発生させてサービスダウンさせてしまった
ECS on EC2での話です。
結論
- ECSのスケールインはマルチAZを優先にスケールインさせる
- ECSのスケールインは条件によってはEC2の削除保護を無視してスケールインされる
- インスタンスタイプ選択時は立てれるアベイラビリティゾーンは確認しよう
再現方法
簡略化させて発生させる再現手順を記載します。
- アベイラビリティゾーンに偏りがある状態でECSのEC2インスタンスを管理する
- 片側のアベイラビリティゾーンだけを対象にEC2の削除保護を設定する
- ECS(CloudformationもしくはAuto Scalingで)の最大台数を減らす
- 削除保護されたEC2がterminatedになる
手順はわかったところで、スクショを交えて手順の説明の実施と再現させます。
ECSインスタンスの状況
まずは前提となる状況を作り出します。
ECSのアベイラビリティゾーンの設定
ECSのアベイラビリティゾーンを2つとします。今回はcとd。
ECSインスタンス達
アベイラビリティゾーンを2ゾーンしか設定していなければ、奇数台数のインスタンスを立てれば偏りが出ます。
このインスタンス達の 削除保護 の状態はこんな感じに片側だけ保護するようにする。スケールインの実施
ここはCloudformationを変更してもいいし、Auto Scalingグループの変更でもどっちでもいいですが、最大台数を落とします。
今回は3台→2台への変更とします。すると、あら不思議!削除保護したインスタンスがterminatedになる。
実業務で発生した状況
グダグダ書きましたが、私自身が実際に起きた状況は以下です。
前提条件
- 該当のECSの アベイラビリティゾーンはaおよびc しか設定されていない
状況
- EC2インスタンスタイプを変更するために最大台数(2→4)とEC2インスタンスタイプを R5a に変更する
- R5aは現状アベイラビリティゾーンaとdしか対応していない ため今回はaに偏って立つ
→この時点で状況を理解していたが、 気にせず次のオペレーションを実施した が最大のミス- 作成された新インスタンスの削除保護を実行
- 旧インスタンスに乗っているコンテナのdrainingを開始
- 旧インスタンスに乗っているコンテナがないことを確認後、Cloudformationで最大台数を戻す(4→2)
- 旧インスタンスの1台はdrainingにも関わらず、アベイラビリティゾーンcであるがゆえに残されて、新インスタンス1台がterminatedになる
- 晴れてterminatedとなった新インスタンスで動いていたコンテナ達は無情にも落とされて、サービスダウンとなる?
正直ここからサービス復旧には30分もかかってないけど(長いと見るか短いと見るかは人それぞれだが、私に長い)、まぁ落ちたのは凹んだ。
最悪なのはECSのCloudformationのアベイラビリティゾーンの設定にdを足しても復旧しなかった。理由はアベイラビリティゾーンdに立ったインスンタンスでコンテナが立ち上がってもALBからのヘルスチェックが通らなかったため。
なぜならECSだけでなく、ALBのアベイラビリティゾーンもdの設定がなかったためです。
急遽ALBにもアベイラビリティゾーンdを足してコンテナを立ち上げたけど、時すでに遅し。最後に
ECSのすべての動作を理解できてなかった検証不足と今後このような悲劇を生み出さないようにと自分への戒めとしてこの記事を書きました。
- 投稿日:2019-06-27T20:14:51+09:00
docker-compose コンテナの停止、ネットワーク・名前付きボリューム・コンテナイメージを削除
コンテナの停止、ネットワーク・名前付きボリューム・コンテナイメージをまとめてスマートに削除できないかと3ヶ月くらい考えていたら良いオプションを発見しました。
神のコマンド
$ docker-compose down --volumes --rmi all Stopping docker-sample_web_1 ... done Stopping docker-sample_app_1 ... done Stopping docker-sample_db_1 ... done Removing docker-sample_web_1 ... done Removing docker-sample_app_1 ... done Removing docker-sample_db_1 ... done Removing network docker-sample_default Removing volume docker-sample_db-store Removing image docker-sample_app Removing image nginx:1.17.0-alpine Removing image mysql:8.0.16
docker volume prune
やdocker volume ls
で探してdocker volume rm
で指定してがんばって削除しなくてよくなったので嬉しいです?付録
$ docker-compose down -h Stops containers and removes containers, networks, volumes, and images created by `up`. By default, the only things removed are: - Containers for services defined in the Compose file - Networks defined in the `networks` section of the Compose file - The default network, if one is used Networks and volumes defined as `external` are never removed. Usage: down [options] Options: --rmi type Remove images. Type must be one of: 'all': Remove all images used by any service. 'local': Remove only images that don't have a custom tag set by the `image` field. -v, --volumes Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. --remove-orphans Remove containers for services not defined in the Compose file -t, --timeout TIMEOUT Specify a shutdown timeout in seconds. (default: 10)
- 投稿日:2019-06-27T18:54:26+09:00
【Airflow on Kubernetes】DockerイメージのbuildとPodのdeployの仕組みについて
概要
Airflowでは、Kubernetes用のDockerイメージの作成スクリプトと、Podのdeploy用のスクリプトが用意されている。
GitHUB: https://github.com/apache/airflowこれらのスクリプトが実際にどのような処理を行っているのかを調べた。
関連記事
おおまかな処理の流れ
処理の流れを大きく分けると、以下の2つに分けられる。
- Dockerイメージをbuildする
- Podをdeployをする
以降で、それぞれの詳細な処理について追っていく。
Dockerイメージをbuildする
Dockerイメージをbuildするための、build.shの処理内容を追う。
実際に実行させる場合は、以下の様にする。
$ sudo ./scripts/ci/kubernetes/docker/build.shbuild.shを実行してairflowのDockerイメージを作成する
build.sh#L46でcompile.shが実行される。
scripts/ci/kubernetes/docker/build.sh#L46docker run -it --rm -v ${AIRFLOW_ROOT}:/airflow \ -w /airflow ${PYTHON_DOCKER_IMAGE} ./scripts/ci/kubernetes/docker/compile.shbuild.shの中でcompile.shが実行される
compile.sh#L32でsetup.pyが実行されると、ホストOSに
~/airflow/dist/
というディレクトリが生成され、その下にapache-airflow-2.0.0.dev0.tar.gz
というファイルが生成される。
これが、airflowのソースコードとなるものである。scripts/ci/kubernetes/docker/compile.sh#L32# apache-airflow-2.0.0.dev0.tar.gzが生成される python setup.py compile_assets sdist -qcompile.shでairflowのtarファイルが作成されると、build.sh#L51で、先程生成された
apache-airflow-2.0.0.dev0.tar.gz
が、scripts/ci/kubernetes/docker/airflow.tar.gz
にリネームしてコピーされる。scripts/ci/kubernetes/docker/build.sh#L51cp $AIRFLOW_ROOT/dist/*.tar.gz ${DIRNAME}/airflow.tar.gzbuild.shの中でairflowのDockerイメージをbuildする
build.sh#L52で、
docker build
が実行される。build.sh#L52cd $DIRNAME && docker build --pull $DIRNAME --tag=${IMAGE}:${TAG}このときに、このDockerfileが読み込まれる。
Dockerfileの処理
Dockerfile#L43で、先程生成されたホストOSの
scripts/ci/kubernetes/docker/airflow.tar.gz
がコンテナ内にCOPYされる。Dockerfile#L43# コンテナ内にCOPY COPY airflow.tar.gz /tmp/airflow.tar.gzDockerfileの中でairflow-test-env-init.shが実行される
次にDockerfile#L46で、airflow-test-env-init.shが実行される。
Dockerfile#L46COPY airflow-test-env-init.sh /tmp/airflow-test-env-init.shすると、airflow-test-env-init.sh#L23で、コンテナ内の
/usr/local/lib/python3.6/site-packages/airflow/example_dags/
を、PersistentVolumeのmount先である/root/airflow/dags/
にコピーする。airflow-test-env-init.sh#L23# example_dags/とcontrib/example_dags/をPersistentVolumeにコピー cd /usr/local/lib/python3.6/site-packages/airflow && \ cp -R example_dags/* /root/airflow/dags/ && \ cp -R contrib/example_dags/example_kubernetes_*.py /root/airflow/dags/ && \ cp -a contrib/example_dags/libs /root/airflow/dags/ && \build.shの処理はこれで完了。
Deploy
Podをdeployするための、deploy.shの処理内容を追う。
実際に実行させる場合は、以下の様にする。
-d
オプションで、dags_folderの追加方法をpersistent_mode
かgit_mode
のどちらかから選ぶ。usage: ./scripts/ci/kubernetes/kube/deploy.sh options OPTIONS: -d Use PersistentVolume or GitSync for dags_folder. Available options are "persistent_mode" or "git_mode"実行
$ sudo ./scripts/ci/kubernetes/kube/deploy.sh -d {persistent_mode,git_mode}deploy.shを実行
deploy.shを実行して、Podをdeployする。
実行されると、scripts/ci/kubernetes/kube/templates以下のmanifestのテンプレートファイルの必要箇所が置換されて、
scripts/ci/kubernetes/kube/build
の下に生成される。
生成されたmanifestファイルを使ってkubectl apply
が実行される。$ ls -1 scripts/ci/kubernetes/kube/templates/ airflow.template.yaml configmaps.template.yaml init_git_sync.template.yamlInitContainer
ci/kubernetes/kube/templates/airflow.template.yamlを元にして生成された、scripts/ci/kubernetes/kube/build/airflow.yamlをapplyすると、airflow.yaml#L69で定義されているInitContainerが実行され、deployの際にInitContainerでもairflow-test-env-init.shが実行される。
ここで、コンテナ内の
/usr/local/lib/python3.6/site-packages/airflow/example_dags/
が、PodのPersistentVolumeのmount先である/root/airflow/dags/
にコピーされる。airflow.template.yaml#一部抜粋spec: initContainers: - name: "init" image: {{AIRFLOW_IMAGE}}:{{AIRFLOW_TAG}} imagePullPolicy: IfNotPresent volumeMounts: - name: airflow-configmap mountPath: /root/airflow/airflow.cfg subPath: airflow.cfg - name: {{INIT_DAGS_VOLUME_NAME}} mountPath: /root/airflow/dags - name: test-volume mountPath: /root/test_volume env: - name: SQL_ALCHEMY_CONN valueFrom: secretKeyRef: name: airflow-secrets key: sql_alchemy_conn command: - "bash" args: - "-cx" - "./tmp/airflow-test-env-init.sh"deploy.shの処理はこれで完了。
dagsの確認
Pod内を確認。/root/airflow/dags/だけでなく、/usr/local/lib/python3.6/site-packages/airflow/example_dags/にもファイルがあることがわかる。
Pod内に入って確認してみる。
$ sudo kubectl exec -it airflow-xxxxxxxxxx-xxxxx /bin/bashPod内の/usr/local/lib/python3.6/site-packages/airflow/example_dags/を確認。
root@airflow-xxxxxxxxxx-xxxxx:/# ls -1 /usr/local/lib/python3.6/site-packages/airflow/example_dags/ __init__.py __pycache__ docker_copy_data.py example_bash_operator.py example_branch_operator.py example_branch_python_dop_operator_3.py example_docker_operator.py example_http_operator.py example_latest_only.py example_latest_only_with_trigger.py example_passing_params_via_test_command.py example_pig_operator.py example_python_operator.py example_short_circuit_operator.py example_skip_dag.py example_subdag_operator.py example_trigger_controller_dag.py example_trigger_target_dag.py example_xcom.py subdags test_utils.py tutorial.pyPod内の/root/airflow/dags/以下を確認。
root@airflow-xxxxxxxxxx-xxxxx:/# ls -1 /root/airflow/dags/ __init__.py __pycache__ docker_copy_data.py example_bash_operator.py example_branch_operator.py example_branch_python_dop_operator_3.py example_docker_operator.py example_http_operator.py example_kubernetes_executor.py example_kubernetes_executor_config.py example_kubernetes_operator.py example_latest_only.py example_latest_only_with_trigger.py example_passing_params_via_test_command.py example_pig_operator.py example_python_operator.py example_short_circuit_operator.py example_skip_dag.py example_subdag_operator.py example_trigger_controller_dag.py example_trigger_target_dag.py example_xcom.py libs subdags test_utils.py tutorial.pyどちらにもdagファイルがあるが、/root/airflow/dags/のほうがファイルが多い。
これはairflow-test-env-init.shを見ると分かるが、example_dags/
だけでなく、contrib/example_dags/
以下のファイルもコピーされているためである。airflow-test-env-init.sh#L23cp -R example_dags/* /root/airflow/dags/ && \ cp -R contrib/example_dags/example_kubernetes_*.py /root/airflow/dags/ && \ cp -a contrib/example_dags/libs /root/airflow/dags/ && \Hackする
同期されるdagファイルを変更する場合
airflow-test-env-init.sh#L23
の以下の箇所を変更することで、同期されるdagファイルを変更することができる。airflow-test-env-init.sh#L23cp -R example_dags/* /root/airflow/dags/ && \ cp -R contrib/example_dags/example_kubernetes_*.py /root/airflow/dags/ && \ cp -a contrib/example_dags/libs /root/airflow/dags/ && \PersistentVolumeのmount先を変更する方法
以下2つのvolumeの定義を変更する。
- airflowのファイル群のmount先
- scripts/ci/kubernetes/kube/volumes.yaml
- postgresのデータのmount先
- scripts/ci/kubernetes/kube/postgres.yaml
参考
- 投稿日:2019-06-27T14:04:55+09:00
EC2にgit、docker、docker-compose、pip、pythonコマンドをインストールする方法
EC2を立ち上げた際にやることを忘れがち&チームに共有としてメモしておきます。
準備まではQiitaの「(下準備編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで」という記事がわかりやすかった。
コマンドのインストール
git
$ sudo yum install gitgitの連携方法は以下
# gotconfigを作成、編集 $ vi .gitconfig [user] name = your_name email = hoge@hoge.com # githubに公開鍵を登録するために公開鍵作成 $ chmod 700 ~/.ssh $ cd ~/.ssh $ ssh-keygen -t rsaあとは、Github/Gitlabに公開鍵を登録してcloneするだけ。
docker
# yum の更新 $ sudo yum update -y # yum から docker をインストール $ sudo yum install -y docker # docker サービスの起動 $ sudo service docker start # ec2-user を docker グループに追加する $ sudo usermod -a -G docker ec2-user # ログインしなおして以下を実行しインストールされていることを確認 $ docker infodocekrコマンドをsudo無しで実行する場合は以下を実行
# dockerグループがなければ作る $ sudo groupadd docker # 現行ユーザをdockerグループに所属させる $ sudo gpasswd -a $USER docker # dockerデーモンを再起動する (CentOS7の場合) $ sudo systemctl restart docker # exitして再ログインすると反映される。 $ exitdocker-compose
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose --version他のリンクにしたい場合以下から探す
https://github.com/docker/compose/releases/byobu
$ sudo yum update -y $ wget https://launchpad.net/byobu/trunk/5.119/+download/byobu_5.119.orig.tar.gz $ tar xzf byobu*.tar.gz $ cd byobu-* && ./configure $ sudo make && sudo make installpip
$ curl -O https://bootstrap.pypa.io/get-pip.py $ python get-pip.py --user # or python3python
# 依存関係インストール $ sudo yum install gcc zlib-devel bzip2 bzip2-devel readline readline-devel sqlite sqlite-devel openssl openssl-devel -y # 本体インストール $ pyenv install 3.6.5 # このOSで使用するPythonのバージョンを宣言 $ pyenv global 3.6.5 $ pyenv rehash $ python --version
- 投稿日:2019-06-27T11:18:13+09:00
docker-composeでopensource COBOL+Postgresql開発環境を作る
概要
コミュニティから、docker-composeを使った開発環境がgithubで公開されていたので、それを利用してみました。
opensource-cobol-develCOBOLと埋め込みSQLを利用したDBアクセス環境が簡単に手に入れられるはずです。
docker-composeを準備
docker-composeをあらかじめ準備する必要があります。
私は以下の記事を参考にさせていただきました。
本家マニュアル
Docker Compose - インストールサンプルを動かしてみる
基本的にはgithubのREADME.mdを参考に実行しています。
まずはリポジトリを持ってきます。
[user@localhost work-docker]$ git clone https://github.com/opensourcecobol/opensource-cobol-devel.git Cloning into 'opensource-cobol-devel'... remote: Enumerating objects: 13, done. remote: Counting objects: 100% (13/13), done. remote: Compressing objects: 100% (11/11), done. remote: Total 13 (delta 1), reused 9 (delta 1), pack-reused 0 Unpacking objects: 100% (13/13), done. [user@localhost work-docker]$ cd opensource-cobol-devel/ [user@localhost opensource-cobol-devel]$ ls LICENSE README.md cpy docker-compose.yml src [user@localhost opensource-cobol-devel]$コンテナを起動します。この際、
-b
オプションでバックエンド実行にしています。[user@localhost opensource-cobol-devel]$ docker-compose up -d Creating opensourcecoboldevel_db_1 ... Creating opensourcecoboldevel_oscobol_1 ... Creating opensourcecoboldevel_db_1 Creating opensourcecoboldevel_db_1 ... done [user@localhost opensource-cobol-devel]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 426febb415ad opensourcecobol/opensource-cobol "/bin/bash" 23 seconds ago Up 18 seconds opensourcecoboldevel_oscobol_1 eaa05a81fdb5 postgres:9.6 "docker-entrypoint.s…" 23 seconds ago Up 18 seconds 5432/tcp opensourcecoboldevel_db_1COBOL用のコンテナ
opensourcecoboldevel_oscobol_1
と、Postgresql用のコンテナopensourcecoboldevel_db_1
が起動しました。続いて、Postgresqlにテスト用のDBを作成します。docoker-composeのexecをつかってcreatedbを実行します。
[user@localhost opensource-cobol-devel]$ docker-compose exec db createdb -U postgres testdb [user@localhost opensource-cobol-devel]$ docker-compose exec db psql -U postgres psql (9.6.12) Type "help" for help. postgres=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+------------+------------+-------------------- --- postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgr es template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgr es testdb | postgres | UTF8 | en_US.utf8 | en_US.utf8 | (4 rows) postgres=# \q [user@localhost opensource-cobol-devel]$正しくtestdbを作成することができました。
この後は、サンプルのCOBOLプログラムを実行し、DBアクセスを行います。
手順通りコンパイルを進めるとINSERTTBL.so
とFETCHTBL.so
ができます。[user@localhost opensource-cobol-devel]$ docker-compose exec oscobol /bin/bash [root@426febb415ad oscobol]# ocesql src/INSERTTBL.cbl INSERTTBL.pre precompile start: src/INSERTTBL.cbl ======================================================= LIST OF CALLED DB Library API ======================================================= Generate:OCESQLConnect Generate:OCESQLExec Generate:OCESQLExec Generate:OCESQLExec Generate:OCESQLExec Generate:OCESQLExecParams Generate:COMMIT Generate:OCESQLDisconnect Generate:ROLLBACK ======================================================= [root@426febb415ad oscobol]# cobc -locesql INSERTTBL.pre [root@426febb415ad oscobol]# ocesql src/FETCHTBL.cbl FETCHTBL.pre precompile start: src/FETCHTBL.cbl ======================================================= LIST OF CALLED DB Library API ======================================================= Generate:OCESQLConnect Generate:OCESQLExecSelectIntoOne Generate:OCESQLCursorDeclare Generate:OCESQLCursorOpen Generate:OCESQLCursorFetchOne Generate:OCESQLCursorFetchOne Generate:OCESQLCursorClose Generate:COMMIT Generate:OCESQLDisconnect Generate:ROLLBACK ======================================================= [root@426febb415ad oscobol]# cobc -locesql FETCHTBL.pre [root@426febb415ad oscobol]# ls FETCHTBL.pre FETCHTBL.so INSERTTBL.pre INSERTTBL.so cpy src実際に実行してみます。
[root@426febb415ad oscobol]# cobcrun INSERTTBL *** INSERTTBL STARTED *** NOTICE: table "emp" does not exist, skipping *** INSERTTBL FINISHED *** [root@426febb415ad oscobol]# cobcrun FETCHTBL *** FETCHTBL STARTED *** TOTAL RECORD: 0012 ---- -------------------- ------ NO NAME SALARY ---- -------------------- ------ 0001 HOKKAI TARO 400 0002 AOMORI JIRO 350 0003 AKITA SABURO 300 0004 IWATE SHIRO -250 0005 MIYAGI GORO -200 0006 FUKUSHIMA RIKURO 150 0007 TOCHIGI SHICHIRO -100 0008 IBARAKI HACHIRO 50 0009 GUMMA KURO -200 0010 SAITAMA JURO 350 0046 KAGOSHIMA ROKURO -320 0047 OKINAWA SHICHIRO 480 *** FETCHTBL FINISHED *** [root@426febb415ad oscobol]#実行結果として、COBOLからINSETデータがFETCHで取得できているように見えます。
Postgresql側から確認します。
[user@localhost opensource-cobol-devel]$ docker-compose exec db psql -U postgres psql (9.6.12) Type "help" for help. postgres=# \c testdb You are now connected to database "testdb" as user "postgres". testdb=# \dt public | emp | table | postgres testdb=# \d emp emp_no | numeric(4,0) | not null emp_name | character(20) | emp_salary | numeric(4,0) | testdb=# select * from emp; 46 | KAGOSHIMA ROKURO | -320 47 | OKINAWA SHICHIRO | 480 1 | HOKKAI TARO | 400 2 | AOMORI JIRO | 350 3 | AKITA SABURO | 300 4 | IWATE SHIRO | -250 5 | MIYAGI GORO | -200 6 | FUKUSHIMA RIKURO | 150 7 | TOCHIGI SHICHIRO | -100 8 | IBARAKI HACHIRO | 50 9 | GUMMA KURO | -200 10 | SAITAMA JURO | 350 testdb=#DB側からもデータが追加されていることが確認できました。
COBOLプログラムを作ってみた
せっかくなので、サンプルプログラムを参考に、自前でプログラムを作って動かしてみます。
筆者が茨城県出身なので、IBARAKI HACHIRO氏の給料を10倍にしたいと思います。まずはホスト側のsrcフォルダに新しいCOBOLファイルを追加します。
[user@localhost opensource-cobol-devel]$ touch src/UPDATETBL.cbl
UPDATETBL.cbl****************************************************************** IDENTIFICATION DIVISION. ****************************************************************** PROGRAM-ID. UPDATETBL. AUTHOR. nor51010. DATE-WRITTEN. 2019-06-27. ****************************************************************** ****************************************************************** DATA DIVISION. ****************************************************************** WORKING-STORAGE SECTION. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 DBNAME PIC X(30) VALUE SPACE. 01 USERNAME PIC X(30) VALUE SPACE. 01 PASSWD PIC X(10) VALUE SPACE. 01 EMP-REC-VARS. 03 EMP-NO PIC S9(04) VALUE ZERO. 03 EMP-NAME PIC X(20) . 03 EMP-SALARY PIC S9(04) VALUE ZERO. EXEC SQL END DECLARE SECTION END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. ****************************************************************** PROCEDURE DIVISION. ****************************************************************** MAIN-RTN. DISPLAY "*** UPDATETBL STARTED ***". * CONNECT MOVE "testdb@db" TO DBNAME. MOVE "postgres" TO USERNAME. MOVE SPACE TO PASSWD. EXEC SQL CONNECT :USERNAME IDENTIFIED BY :PASSWD USING :DBNAME END-EXEC. IF SQLCODE NOT = ZERO PERFORM ERROR-RTN STOP RUN. * SELECT IBARAKI san INTO HOST-VARIABLE EXEC SQL SELECT * INTO :EMP-NO, :EMP-NAME, :EMP-SALARY FROM EMP WHERE EMP_NO = 8 END-EXEC. IF SQLCODE NOT = ZERO PERFORM ERROR-RTN STOP RUN. * SALARY * 10 COMPUTE EMP-SALARY = EMP-SALARY * 10. * UPDATE IBARAKI san EXEC SQL UPDATE emp SET EMP_SALARY = :EMP-SALARY WHERE EMP_NO = 8 END-EXEC. IF SQLCODE NOT = ZERO PERFORM ERROR-RTN STOP RUN. * COMMIT EXEC SQL COMMIT WORK END-EXEC. * DISCONNECT EXEC SQL DISCONNECT ALL END-EXEC. * END DISPLAY "*** UPDATETBL FINISHED ***". STOP RUN. ****************************************************************** ERROR-RTN. ****************************************************************** DISPLAY "*** SQL ERROR ***". DISPLAY "SQLCODE: " SQLCODE " " NO ADVANCING. EVALUATE SQLCODE WHEN +10 DISPLAY "Record not found" WHEN -01 DISPLAY "Connection falied" WHEN -20 DISPLAY "Internal error" WHEN -30 DISPLAY "PostgreSQL error" DISPLAY "ERRCODE: " SQLSTATE DISPLAY SQLERRMC *> TO RESTART TRANSACTION, DO ROLLBACK. EXEC SQL ROLLBACK END-EXEC WHEN OTHER DISPLAY "Undefined error" DISPLAY "ERRCODE: " SQLSTATE DISPLAY SQLERRMC END-EVALUATE. ******************************************************************では実際にコンパイルして実行していきます。srcフォルダはdocker-compose.ymlの設定でCOBOLコンテナと共有されているため、コンテナに入りコマンドをたたいていきます。
[user@localhost opensource-cobol-devel]$ docker-compose exec oscobol /bin/bash [root@426febb415ad oscobol]# ls src/ FETCHTBL.cbl INSERTTBL.cbl UPDATETBL.cbl [root@426febb415ad oscobol]# ocesql src/UPDATETBL.cbl UPDATETBL.pre precompile start: src/UPDATETBL.cbl ======================================================= LIST OF CALLED DB Library API ======================================================= Generate:OCESQLConnect Generate:OCESQLExecSelectIntoOne Generate:OCESQLExecParams Generate:COMMIT Generate:OCESQLDisconnect Generate:ROLLBACK ======================================================= [root@426febb415ad oscobol]# cobc -locesql UPDATETBL.pre [root@426febb415ad oscobol]# ls FETCHTBL.pre INSERTTBL.pre UPDATETBL.pre cpy FETCHTBL.so INSERTTBL.so UPDATETBL.so src [root@426febb415ad oscobol]# cobcrun INSERTTBL *** INSERTTBL STARTED *** *** INSERTTBL FINISHED *** [root@426febb415ad oscobol]# cobcrun UPDATETBL *** UPDATETBL STARTED *** *** UPDATETBL FINISHED *** [root@426febb415ad oscobol]# cobcrun FETCHTBL *** FETCHTBL STARTED *** TOTAL RECORD: 0012 ---- -------------------- ------ NO NAME SALARY ---- -------------------- ------ 0001 HOKKAI TARO 400 0002 AOMORI JIRO 350 0003 AKITA SABURO 300 0004 IWATE SHIRO -250 0005 MIYAGI GORO -200 0006 FUKUSHIMA RIKURO 150 0007 TOCHIGI SHICHIRO -100 0008 IBARAKI HACHIRO 500 0009 GUMMA KURO -200 0010 SAITAMA JURO 350 0046 KAGOSHIMA ROKURO -320 0047 OKINAWA SHICHIRO 480 *** FETCHTBL FINISHED ***これまでと同様に、DB側も確認していきます。
[user@localhost opensource-cobol-devel]$ docker-compose exec db psql -U postgres psql (9.6.12) Type "help" for help. postgres=# \c testdb You are now connected to database "testdb" as user "postgres". testdb=# select * from emp ; emp_no | emp_name | emp_salary --------+----------------------+------------ 46 | KAGOSHIMA ROKURO | -320 47 | OKINAWA SHICHIRO | 480 1 | HOKKAI TARO | 400 2 | AOMORI JIRO | 350 3 | AKITA SABURO | 300 4 | IWATE SHIRO | -250 5 | MIYAGI GORO | -200 6 | FUKUSHIMA RIKURO | 150 7 | TOCHIGI SHICHIRO | -100 9 | GUMMA KURO | -200 10 | SAITAMA JURO | 350 8 | IBARAKI HACHIRO | 500 (12 rows) testdb=#無事にIBARAKI氏の給料を上げることができました。
まとめ
やはりコンテナ環境は偉大だなと感じられる環境です。
設定等を考えずとも、埋め込みSQLを利用したCOBOLの開発・実行環境がコマンド1発でできるため、すでに持っているCOBOLをとりあえず動かしてみるとかといった時に簡単にできそうです。
DBとの連携に関しても、COBOLのデータ型からPostgresにちゃんとデータを追加できていました。
サンプルでは給料がマイナスの社員さん達がいますが、マイナス符号の数値も問題なく扱え、一般的なCOBOLデータを扱っている埋め込みSQL付きアプリケーションはそのまま持って行けそうです。※Postgresql以外もいけるといいな
- 投稿日:2019-06-27T07:27:41+09:00
CircleCIでdocker-composeは最強
はじめに
みなさんはローカルの開発環境はdocker-composeで管理していますか?
私はもう新しく作っているプロジェクトは全て、docker-composeで作っています。imageを指定して簡単に起動でき、サービス間の通信もdepends_onで指定するだけでOKなのはすごく助かります。
CircleCIではv2になってからDockerをサポートするようになり、簡単にサービスを立ち上げることができるようになりました。
そこで感じたのが、開発環境で使っている
docker-compose.yml
をそのままCircleCIでも使用できれば、わざわざCircleCI用の定義を書かなくてよくなるのでは?、ということです。結果
できました。つまり、 開発環境=テスト環境(CircleCI上)を実現できました!
これで、開発環境とテスト環境でのサービス(MySQL etc)のバージョンが違ったとか、開発環境だとうまく動くのにテスト環境だとうまく動かないっていうのがなくなると思います!公開しているリポジトリに実際のCircleCIのconfigがあるので、興味がある方は使用してみてください。
行ってるステップは以下の通りです。
- docker composeをインストールし指定の場所にファイルを移動させます
- いつも通りdocker composeを起動させます
- 一度stopさせているのは、原因はよくわからないんですが一回目の起動時は、うまくサービスが起動できないからです
- 二度目の起動を行います
- rspecを実行します
- docker composeをdownさせます
.circleci/config.ymlversion: 2 jobs: build: machine: image: circleci/classic:edge working_directory: ~/repo steps: - checkout - run: name: Install Docker Compose command: | curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` > ~/docker-compose chmod +x ~/docker-compose sudo mv ~/docker-compose /usr/local/bin/docker-compose - run: name: docker-compose up command: | set -x docker-compose up --build -d - run: name: docker-compose stop command: | set -x docker-compose stop - run: name: docker-compose up command: | set -x docker-compose up -d - run: name: test command: | mkdir /tmp/test-results TEST_FILES="$(circleci tests glob 'spec/**/*_spec.rb' | circleci tests split --split-by=timings)" docker-compose exec rails_api bin/rspec --format progress \ --format RspecJunitFormatter \ --out /tmp/test-results/rspec.xml \ $TEST_FILES - run: name: docker-compose down command: docker-compose downまとめ
これでまた一つ管理することが減ったので、DXの改善になったのではないでしょうか!是非、お試しください。
- 投稿日:2019-06-27T00:35:06+09:00
Vue + Vue Router + Vuex + Laravel 写真共有アプリチュートリアルの環境をDockerで構築する
はじめに
今年1月にQiitaに投稿されて以来、1,500以上のいいねを獲得している下記の人気チュートリアル。
Laravel + Vue.jsでのSPA開発のほか、Laravelでのテストコードの書き方など幅広い知識が同時に学べ、非常にオススメです。
このチュートリアルでは、開発環境構築にLaravel Valetを使っていますが、私の場合はDocker(Laradock)で環境を構築しました。
Dockerで環境を構築したい方は、参考にしてみてください。
環境
- macOS High Sierra 10.13.6
- Docker 18.09.2
ディレクトリ構造
本記事での環境構築を終えると、下記のディレクトリ構造が出来上がります。
├── data // データベースのディレクトリ ├── laradock // Docker関連ファイルのディレクトリ └── vuesplash // Laravelのルートディレクトリ環境構築手順
本記事での環境構築手順は、
Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (3) SPA開発環境とVue Router
の
「Laravelプロジェクトを作成する」 〜 「フロントエンドの準備」の直前
までに相当します。
チュートリアルの
までを読み進めたら、本記事での環境構築を実施し、その後は「フロントエンドの準備」から先を進めてください。
1. Laradockのコピー
プロジェクトのルートとなるディレクトリに、Laradockをコピーします。
$ git clone https://github.com/Laradock/laradock.git2. Laradockの.envファイルの編集
laradock
ディレクトリが出来上がるので、その配下のenv-example
ファイルをコピーし、.env
ファイルを作成します。$ cd laradock laradock $ cp env-example .env
laradock/.env
の以下2つの設定を編集します。laradock/.envAPP_CODE_PATH_HOST=../vuesplash DATA_PATH_HOST=../data3. PostgreSQLのバージョンの指定
チュートリアルではPostgreSQLのバージョン指定はありませんが、9.6.12を使用することにします。
PostgreSQLのDockerファイルを以下の通り編集します。laradock/postgres/DockerfileFROM postgres:9.6.12 LABEL maintainer="Ben M <git@bmagg.com>" CMD ["postgres"] EXPOSE 54324. コンテナのビルド
コンテナをビルドします。
laradock $ docker-compose up -d --build workspace postgres php-fpm nginx5. Laravelのインストール
Laravelをインストールします。
バージョンはチュートリアルで使用されている5.7.19
にします。下記コマンドを実行してください。
laravel/laravel . "5.7.19"
の部分にある.
を忘れずに入力してください。laradock $ docker-compose exec workspace composer create-project --prefer-dist laravel/laravel . "5.7.19"6. Laravelの.envファイルの編集
Laravelの.envファイルを編集し、LaravelからPostgreSQLに接続できるようにします。
vuesplash/.envDB_CONNECTION=pgsql DB_HOST=postgres DB_PORT=5432 DB_DATABASE=sample DB_USERNAME=default DB_PASSWORD=secret7. データベースを作成する
まず、PostgreSQLに接続します。
laradock $ docker-compose exec workspace psql -U default -h postgresパスワードを入力します。
Password for user default:続いて、データベースを作成します。
データベース名は、チュートリアルで指定されているvuesplash
にします。default=# create database vuesplash;PostgreSQLとの接続を終了します。
default=# \q8. Laravelのlocale設定を日本にする
vuesplash/config/app.php<?php return [ // 略 'locale' => 'ja', // 略 ];9. Laravelの動作確認
http://localhost/
にブラウザでアクセスし、LaravelのWelcome画面が表示されることを確認してください。10. 後はチュートリアルを再開してください
ここまでの作業が完了したら、チュートリアルの「フロントエンドの準備」から先を進めてください。
なお、チュートリアル記事中でコマンドを実行するよう記載があった場合は、例えばそれが
npm install
であればlaradock $ docker-compose exec workspace npm installといった具合に実行すればOKです。
最後に
以上です。
本記事が、この素晴らしいチュートリアルに取り組む方のお役に立てば幸いです
- 投稿日:2019-06-27T00:19:20+09:00
コンテナの指揮者、Docker Composeのおはなし
Docker Composeとは
「複数のDockerコンテナを、諸々の設定含め一発で一気に起動できちゃうよ」な便利道具
いくつかのDockerコンテナを立ち上げて環境構築しようと思った時に毎回docker runで全部立ち上げるのは大変です。
そんな時にまさに指揮者(Composer)のようにコンテナを自由自在に扱えるようにしてくれるのがDocker Composeです!
Docker Composeの使い方
Docker Compose起動!!
と言っても起動はしてくれません。
docker-compose.yml
(もしくはdocker-compose.yaml)というファイルに設定をつらつら書いていきます。
なんだ、スクリプトファイル書くのと変わらんやん、と思うかもしれません。
正直僕も違いはそこまでわかりませんが、断然簡単です!(らしい)
僕がDockerに触れ始めた時にはもうComposeもあったので...
とりあえずdocker-compose.ymlの中身を見ていきましょう!
docker-compose.yml
docker-compose.ymlservices: fabric-ca: image: hyperledger/fabric-ca ports: - "7054:7054" volumes: - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config container_name: fabric-ca networks: - basic couchdb: container_name: couchdb image: hyperledger/fabric-couchdb environment: - COUCHDB_USER=xxx - COUCHDB_PASSWORD=xxx ports: - 5984:5984 networks: - basicこんな感じです。
Hyperledger Fabricのfabcarサンプルで使うファイルを省略してみました。dockerを使ったことがあると大体掴めると思います。
servicesがそれぞれのコンテナで、その下の階層でオプションを指定します
image でイメージを指定
ports でホストのポートと対応するコンテナのポートを指定
volumes でホストのディレクトリとコンテナ内のディレクトリをマウント
container_name で名前を設定。コンテナIDを使わなくても名前でアクセスできるようになったりしてわかりやすい。
environment でコンテナ内の環境変数をセットできる。
networks でコンテナをどのネットワークに置くか指定できる。デフォルトだとおそらくbridgeネットワークです。他にもdockerコマンドのオプションに対応するものは大体あると思います。
オプションの順番がfabric-caとcouchdbでバラバラなのが少し気持ち悪いですが、まあこんな風に適当にもかけちゃうよってことですね。
docker-composeコマンド
docker-compose.ymlファイルが書けたらもうほとんど終わりです!
あとはコマンドを打ち込む!
下記はいくつかよく使うコマンドです#コンテナ全部起動 docker-compose up #デタッチドモードでバックグラウンドで起動 docker-compose up -d #コンテナ全部終了 docker-compose stop #コンテナを全削除 docker-compose rm #コンテナのログを出力 docker-compose logs他にも色々あります
先ほどのドキュメントやヘルプをご参照ください!まとめ
Docker Composeが便利だよと言うお話でした。
昔はローカルでシステムの環境構築するのに数日かかることもあったとか、なかったとか。
便利な世の中になりました。
先人達に感謝。今度は最近話題のKubernetesについても勉強してまとめてみたいと思います。
Kubernetesについてよく出てくるワードが
「コンテナオーケストレーション」
オーケストラのように調和のとれた秩序ある環境を構築するということなのでしょうか。
指揮者のさらに上をいく技術っぽそうな感じがプンプンしてきます。
楽しみです。
- 投稿日:2019-06-27T00:07:03+09:00
docker-composeのrails環境で、bootstrap4が反映されない時〜
DockerでRailsの開発環境を構築したのですが、Bootstrap4の導入でハマったため投稿します。
公式サイトの手順に沿ってインストール
まず以下の公式サイトに従って導入しました。
Bootstrap4エラー発生
ActionView::Template::Error (Autoprefixer doesn’t support Node v4.8.2. Update it.):
AutoprefixerがNode v4.8.2のサポートしていないため、updateしてくださいエラー。
大人しくアップデートするか、もしくは以下のgemをGemfileに追記。Gemfilegem 'mini_racer'
bundle installを実行。
またエラー発生
ActionView::Template::Error (File to import not found or unreadable: bootstrap.
bootstrapを読み込めないというエラー。
bundle installを実行しているのになぜだろうとログを見ていると、
何回実行してもinstalling bootstrap4が走っている。
これキャッシュ関係してるとかある・・・?と疑問に思い調べてみました。
以下を実行し、エラーは解消できました。docker-compose build --no-cache
めでたくbootstrap4導入完了
アプリ画面を確認するとちゃんとbootstrapがちゃんと反映されていました!
調べている最中は悔しい気持ちでいっぱいになるのに、
なんだかんだずっと続けられるのは、達成した喜びがあるからかなと改めて感じました。