20190627のdockerに関する記事は9件です。

EC2の削除保護を無視してterminatedなる状況を発生させてサービスダウンさせてしまった

ECS on EC2での話です。

結論

  • ECSのスケールインはマルチAZを優先にスケールインさせる
  • ECSのスケールインは条件によってはEC2の削除保護を無視してスケールインされる
  • インスタンスタイプ選択時は立てれるアベイラビリティゾーンは確認しよう

再現方法

簡略化させて発生させる再現手順を記載します。

  1. アベイラビリティゾーンに偏りがある状態でECSのEC2インスタンスを管理する
  2. 片側のアベイラビリティゾーンだけを対象にEC2の削除保護を設定する
  3. ECS(CloudformationもしくはAuto Scalingで)の最大台数を減らす
  4. 削除保護されたEC2がterminatedになる

手順はわかったところで、スクショを交えて手順の説明の実施と再現させます。

ECSインスタンスの状況

まずは前提となる状況を作り出します。

ECSのアベイラビリティゾーンの設定

ECSのアベイラビリティゾーンを2つとします。今回はcとd。

image url.jpg

ECSインスタンス達

アベイラビリティゾーンを2ゾーンしか設定していなければ、奇数台数のインスタンスを立てれば偏りが出ます。
このインスタンス達の 削除保護 の状態はこんな感じに片側だけ保護するようにする。

image url (1).jpg

image url (2).jpg

スケールインの実施

ここはCloudformationを変更してもいいし、Auto Scalingグループの変更でもどっちでもいいですが、最大台数を落とします。
今回は3台→2台への変更とします。

image url (3).jpg

すると、あら不思議!削除保護したインスタンスがterminatedになる。

image url (4).jpg

実業務で発生した状況

グダグダ書きましたが、私自身が実際に起きた状況は以下です。

前提条件

  1. 該当のECSの アベイラビリティゾーンはaおよびc しか設定されていない

状況

  1. EC2インスタンスタイプを変更するために最大台数(2→4)とEC2インスタンスタイプを R5a に変更する
  2. R5aは現状アベイラビリティゾーンaとdしか対応していない ため今回はaに偏って立つ
    →この時点で状況を理解していたが、 気にせず次のオペレーションを実施した が最大のミス
  3. 作成された新インスタンスの削除保護を実行
  4. 旧インスタンスに乗っているコンテナのdrainingを開始
  5. 旧インスタンスに乗っているコンテナがないことを確認後、Cloudformationで最大台数を戻す(4→2)
  6. 旧インスタンスの1台はdrainingにも関わらず、アベイラビリティゾーンcであるがゆえに残されて、新インスタンス1台がterminatedになる
  7. 晴れてterminatedとなった新インスタンスで動いていたコンテナ達は無情にも落とされて、サービスダウンとなる?

正直ここからサービス復旧には30分もかかってないけど(長いと見るか短いと見るかは人それぞれだが、私に長い)、まぁ落ちたのは凹んだ。
最悪なのはECSのCloudformationのアベイラビリティゾーンの設定にdを足しても復旧しなかった。理由はアベイラビリティゾーンdに立ったインスンタンスでコンテナが立ち上がってもALBからのヘルスチェックが通らなかったため。
なぜならECSだけでなく、ALBのアベイラビリティゾーンもdの設定がなかったためです。
急遽ALBにもアベイラビリティゾーンdを足してコンテナを立ち上げたけど、時すでに遅し。

最後に

ECSのすべての動作を理解できてなかった検証不足と今後このような悲劇を生み出さないようにと自分への戒めとしてこの記事を書きました。

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

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

【Airflow on Kubernetes】DockerイメージのbuildとPodのdeployの仕組みについて

概要

Airflowでは、Kubernetes用のDockerイメージの作成スクリプトと、Podのdeploy用のスクリプトが用意されている。
GitHUB: https://github.com/apache/airflow

これらのスクリプトが実際にどのような処理を行っているのかを調べた。

関連記事

おおまかな処理の流れ

処理の流れを大きく分けると、以下の2つに分けられる。

  1. Dockerイメージをbuildする
    1. scripts/ci/kubernetes/docker/build.sh
  2. Podをdeployをする
    1. scripts/ci/kubernetes/kube/deploy.sh

以降で、それぞれの詳細な処理について追っていく。

Dockerイメージをbuildする

Dockerイメージをbuildするための、build.shの処理内容を追う。

実際に実行させる場合は、以下の様にする。

$ sudo ./scripts/ci/kubernetes/docker/build.sh

build.shを実行してairflowのDockerイメージを作成する

build.sh#L46compile.shが実行される。

scripts/ci/kubernetes/docker/build.sh#L46
docker run -it --rm -v ${AIRFLOW_ROOT}:/airflow \
    -w /airflow ${PYTHON_DOCKER_IMAGE} ./scripts/ci/kubernetes/docker/compile.sh

build.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 -q

compile.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#L51
cp $AIRFLOW_ROOT/dist/*.tar.gz ${DIRNAME}/airflow.tar.gz

build.shの中でairflowのDockerイメージをbuildする

build.sh#L52で、docker buildが実行される。

build.sh#L52
cd $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.gz

Dockerfileの中でairflow-test-env-init.shが実行される

次にDockerfile#L46で、airflow-test-env-init.shが実行される。

Dockerfile#L46
COPY 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_modegit_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.yaml

InitContainer

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#L69

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/bash

Pod内の/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.py

Pod内の/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#L23
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/ && \

Hackする

同期されるdagファイルを変更する場合

airflow-test-env-init.sh#L23
の以下の箇所を変更することで、同期されるdagファイルを変更することができる。

airflow-test-env-init.sh#L23
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/ && \

PersistentVolumeのmount先を変更する方法

以下2つのvolumeの定義を変更する。

  • airflowのファイル群のmount先
    • scripts/ci/kubernetes/kube/volumes.yaml
  • postgresのデータのmount先
    • scripts/ci/kubernetes/kube/postgres.yaml

参考

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

EC2にgit、docker、docker-compose、pip、pythonコマンドをインストールする方法

EC2を立ち上げた際にやることを忘れがち&チームに共有としてメモしておきます。

準備まではQiitaの「(下準備編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで」という記事がわかりやすかった。

コマンドのインストール

git

$ sudo yum install git

gitの連携方法は以下

# 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 info

docekrコマンドをsudo無しで実行する場合は以下を実行

# dockerグループがなければ作る
$ sudo groupadd docker

# 現行ユーザをdockerグループに所属させる
$ sudo gpasswd -a $USER docker

# dockerデーモンを再起動する (CentOS7の場合)
$ sudo systemctl restart docker

# exitして再ログインすると反映される。
$ exit

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

pip

$ curl -O https://bootstrap.pypa.io/get-pip.py
$ python get-pip.py --user # or python3

python

# 依存関係インストール
$ 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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-composeでopensource COBOL+Postgresql開発環境を作る

概要

コミュニティから、docker-composeを使った開発環境がgithubで公開されていたので、それを利用してみました。
opensource-cobol-devel

COBOLと埋め込み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_1

COBOL用のコンテナ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.soFETCHTBL.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以外もいけるといいな

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

CircleCIでdocker-composeは最強

はじめに

みなさんはローカルの開発環境はdocker-composeで管理していますか?
私はもう新しく作っているプロジェクトは全て、docker-composeで作っています。

imageを指定して簡単に起動でき、サービス間の通信もdepends_onで指定するだけでOKなのはすごく助かります。

CircleCIではv2になってからDockerをサポートするようになり、簡単にサービスを立ち上げることができるようになりました。

そこで感じたのが、開発環境で使っている docker-compose.yml をそのままCircleCIでも使用できれば、わざわざCircleCI用の定義を書かなくてよくなるのでは?、ということです。

結果

できました。つまり、 開発環境=テスト環境(CircleCI上)を実現できました!
これで、開発環境とテスト環境でのサービス(MySQL etc)のバージョンが違ったとか、開発環境だとうまく動くのにテスト環境だとうまく動かないっていうのがなくなると思います!

公開しているリポジトリに実際のCircleCIのconfigがあるので、興味がある方は使用してみてください。

行ってるステップは以下の通りです。

  1. docker composeをインストールし指定の場所にファイルを移動させます
  2. いつも通りdocker composeを起動させます
  3. 一度stopさせているのは、原因はよくわからないんですが一回目の起動時は、うまくサービスが起動できないからです
  4. 二度目の起動を行います
  5. rspecを実行します
  6. docker composeをdownさせます
.circleci/config.yml
version: 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の改善になったのではないでしょうか!是非、お試しください。

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

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

2. Laradockの.envファイルの編集

laradockディレクトリが出来上がるので、その配下のenv-exampleファイルをコピーし、.envファイルを作成します。

$ cd laradock
laradock $ cp env-example .env

laradock/.envの以下2つの設定を編集します。

laradock/.env
APP_CODE_PATH_HOST=../vuesplash

DATA_PATH_HOST=../data

3. PostgreSQLのバージョンの指定

チュートリアルではPostgreSQLのバージョン指定はありませんが、9.6.12を使用することにします。
PostgreSQLのDockerファイルを以下の通り編集します。

laradock/postgres/Dockerfile
FROM postgres:9.6.12

LABEL maintainer="Ben M <git@bmagg.com>"

CMD ["postgres"]

EXPOSE 5432

4. コンテナのビルド

コンテナをビルドします。

laradock $ docker-compose up -d --build workspace postgres php-fpm nginx

5. 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/.env
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=sample
DB_USERNAME=default
DB_PASSWORD=secret

7. データベースを作成する

まず、PostgreSQLに接続します。

laradock $ docker-compose exec workspace psql -U default -h postgres

パスワードを入力します。

Password for user default: 

続いて、データベースを作成します。
データベース名は、チュートリアルで指定されているvuesplashにします。

default=# create database vuesplash;

PostgreSQLとの接続を終了します。

default=# \q

8. 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です。

最後に

以上です。

本記事が、この素晴らしいチュートリアルに取り組む方のお役に立てば幸いです:wink:

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

コンテナの指揮者、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.yml

services:
 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コマンド

docker-compose.ymlファイルが書けたらもうほとんど終わりです!

あとはコマンドを打ち込む!
下記はいくつかよく使うコマンドです

#コンテナ全部起動
docker-compose up
#デタッチドモードでバックグラウンドで起動
docker-compose up -d
#コンテナ全部終了
docker-compose stop
#コンテナを全削除
docker-compose rm
#コンテナのログを出力
docker-compose logs

他にも色々あります
先ほどのドキュメントやヘルプをご参照ください!

まとめ

Docker Composeが便利だよと言うお話でした。

昔はローカルでシステムの環境構築するのに数日かかることもあったとか、なかったとか。
便利な世の中になりました。
先人達に感謝。

今度は最近話題のKubernetesについても勉強してまとめてみたいと思います。

Kubernetesについてよく出てくるワードが

「コンテナオーケストレーション」

オーケストラのように調和のとれた秩序ある環境を構築するということなのでしょうか。

指揮者のさらに上をいく技術っぽそうな感じがプンプンしてきます。

楽しみです。

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

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に追記。

Gemfile
gem '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がちゃんと反映されていました!
調べている最中は悔しい気持ちでいっぱいになるのに、
なんだかんだずっと続けられるのは、達成した喜びがあるからかなと改めて感じました。

参考サイト:
Bootstrap4
Dockerでコンテナ内にbundle installされない問題の解決法

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