- 投稿日:2020-02-04T23:06:55+09:00
社内環境で Docker for Windows を使うときにハマったこと
普段 Docker (for Linux) を利用している人が Docker for Windows を試したらドツボにハマったのでメモ。
server gave HTTP response to HTTPS client => insecure registry を追加する
社内環境に立てた Docker Registry が HTTPS に対応していない場合、イメージを pull したときに以下のようなエラーが発生します:
ERROR: Get http://<社内レジストリ>:5000 http: server gave HTTP response to HTTPS clientこのような場合、当該レジストリを insecure registry として登録すれば解決します。Linux の場合は
/etc/docker/daemon.jsonを編集しますが、Docker for Windows の場合は [Settings] - [Docker Engine] で編集します:daemon.json{ "insecure-registries" : ["<社内レジストリ>:5000"] }このとき注意すべきことは、プロコトルは記述しないということです。記述しても問題なく適用&再起動できてしまうので注意してください。間違った設定のせいで Settings が開けなくなった場合はあきらめて再インストールしてください。
dial tcp: lookup registry-1.docker.io: no such host. => プロキシを設定する
社外環境にある Docker Registory (公式など) から pull したときに以下のようなエラーが発生する場合があります:
docker: Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: no such host.そんなホストみつからないよ!といっていますが DNS の問題ではなく、プロキシが効いていないためのエラーです。そのため、[Settings] - [Resources] - [Proxies] でプロキシの設定を行います。プロキシサーバに BASIC 認証がかかっている場合は以下のように設定します。
http://<ユーザ名>:<パスワード>@<プロキシサーバ>:<ポート>これでも同様なエラーが発生する場合は、[Settings] - [Resources] - [Network] で DNS として
8.8.8.8を指定するとパスできるという情報もありますが詳細は混沌の中です。参考リンク
- 投稿日:2020-02-04T19:41:22+09:00
Docker for WindowsでLaravel+OCI8の複数プロジェクト開発環境を作ってみた
普段レガシーなシステムをごにょごにょお世話しているレガシーなプログラマーです。
中高年でもイマドキ風の開発をやってみたい!
でも仕事で使うDBはうちはORACLEが多い…
ということで、LaravelでOCIを使える環境を作ってみました。普通に開発環境を作るならLaraDockが色々揃っていますし、他に良い記事が沢山あると思います
Laravelの開発環境をDockerを使って構築するDocker Desktop on Windowsのインストール
まずはDockerの準備です。動作条件を確認。
- Windows10 pro 64bit
- メモリは4GB以上
- Hyper-Vが使えること
ほぼこちらの説明通りで設定できました。ありがとうございます!
https://qiita.com/ksh-fthr/items/6b1242c010fac7395a45ダウンロード&インストール
公式サイトからインストーラーをダウンロードします。
この時、Docker Hubのアカウントも作成することになります。サクッと登録しましょう。https://docs.docker.com/docker-for-windows/install/
docker-composeのインストール
Docker for Macは個別に入れなくてもよかったのですがWindows版は手動で入れないといけません。
1.Powershell を管理者権限で起動する。
2.以下のコマンドを実行する。DockerのUpdateのたびに実行する必要があるのがメンドイ。Invoke-WebRequest "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-Windows-x86_64.exe" -UseBasicParsing -OutFile $Env:ProgramFiles\docker\docker-compose.exeShared Drivesの設定
チェックを入れて「Apply」をクリック。
Dockerを再起動してちゃんと設定できているか確認します。
docker-compose.yml作成
こんな構成で作成しました。
[lara73oci]
├ docker-compose.yml
├ [nginx]
│ ├ [sites] <=ここにサイトの設定を入れる
│ ├ Dockerfile
│ └ nginx.conf
├ [php7.3]
│ ├ Dockerfile
│ ├ instantclient-basic-linux.x64-12.2.0.1.0.zip <=Oracleからダウンロードしてきます
│ ├ instantclient-sdk-linux.x64-12.2.0.1.0.zip <=Oracleからダウンロードしてきます
│ ├ php.ini
│ └ tnsnames.ora
├ [src] <=ここにプログラム
└ [logs] <=nginxのログdocker-compose.ymlversion: '3' services: nginx: build: context: ./nginx volumes: - ./src:/var/www:cached - ./logs/nginx/:/var/log/nginx - ./nginx/sites/:/etc/nginx/sites-available ports: - "80:80" depends_on: - php-fpm php-fpm: build: context: ./php7.3 dockerfile: Dockerfile volumes: - ./php7.3/php.ini:/usr/local/etc/php/php.ini - ./php7.3/tnsnames.ora:/usr/local/instantclient/tnsnames.ora - ./src:/var/www:cached expose: - "9000"複数プロジェクトを動かしたかったのでsites-availableを使っています。
nginx
nginx/DockerfileFROM nginx:alpine COPY nginx.conf /etc/nginx/ RUN apk update \ && apk upgrade \ && apk add --no-cache bash RUN set -x ; \ addgroup -g 82 -S www-data ; \ adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1 RUN rm /etc/nginx/conf.d/default.conf CMD ["nginx"] EXPOSE 80 443nginx/nginx.confuser www-data; worker_processes 4; pid /run/nginx.pid; daemon off; events { worker_connections 2048; multi_accept on; use epoll; } http { server_tokens off; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 15; types_hash_max_size 2048; client_max_body_size 20M; include /etc/nginx/mime.types; default_type application/octet-stream; access_log /dev/stdout; error_log /dev/stderr; gzip on; gzip_disable "msie6"; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-available/*.conf; open_file_cache off; # Disabled for issue 619 charset UTF-8; }サイトの設定です。
nginx/sites/default.confserver { listen 80 default_server; listen [::]:80 default_server ipv6only=on; server_name localhost; root /var/www/public; index index.php index.html index.htm; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri /index.php =404; fastcgi_pass php-fpm:9000; fastcgi_index index.php; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; #fixes timeouts fastcgi_read_timeout 600; include fastcgi_params; } location ~ /\.ht { deny all; } location /.well-known/acme-challenge/ { root /var/www/letsencrypt/; log_not_found off; } }複数プロジェクトで使用する場合
nginx/sitesのproject1.confをコピーして使用してください
(例)project_hoge.conf
ファイル内のproject1、project1.local を自分のプロジェクトに合わせて変更してください
もちろんDocument rootも!PHP+OCI8
Oracle instant clientの入手
Instant Client for Linux x86-64からinstantclient-basicとinstantclient-sdkをzip形式でダウンロードして
php7.3のDockerFileと同じディレクトリに置いてください
バージョンは12.2と12.1で確認しました
(例)
./php7.3/instantclient-sdk-linux.x64-12.2.0.1.0.zip
./php7.3/instantclient-basic-linux.x64-12.2.0.1.0.zipphp7.3/DockerFileの編集
入手したファイル名に合わせて13~25行目を変更してください
php7.3/tnsnames.oraの編集
ご自分の環境に合わせて記述してください
php7.3/DockerfileFROM php:7.3-fpm RUN apt-get update && \ apt-get install -y git \ libfreetype6-dev \ libjpeg62-turbo-dev \ libpng-dev && \ docker-php-ext-install gd pdo_mysql mysqli mbstring bcmath ENV LD_LIBRARY_PATH /usr/local/instantclient/ ENV TNS_ADMIN /usr/local/instantclient/ COPY instantclient-basic-linux.x64-12.2.0.1.0.zip /tmp COPY instantclient-sdk-linux.x64-12.2.0.1.0.zip /tmp RUN apt-get update && \ apt-get install -y zip unzip libaio1 wget && \ unzip /tmp/instantclient-basic-linux.x64-12.2.0.1.0.zip -d /usr/local/ && \ unzip /tmp/instantclient-sdk-linux.x64-12.2.0.1.0.zip -d /usr/local/ && \ ln -s /usr/local/instantclient_12_2 /usr/local/instantclient && \ ln -s /usr/local/instantclient/libclntsh.so.12.1 /usr/local/instantclient/libclntsh.so && \ export LD_LIBRARY_PATH=/usr/local/instantclient && \ docker-php-ext-configure oci8 --with-oci8=instantclient,/usr/local/instantclient && \ docker-php-ext-install oci8 && \ docker-php-ext-configure pdo_oci --with-pdo-oci=instantclient,/usr/local/instantclient,12.2 && \ docker-php-ext-install pdo_oci && \ rm -rf /usr/local/*.zip RUN apt-get install -y \ curl \ gnupg RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - RUN apt-get install -y nodejs RUN npm install npm@latest -g COPY --from=composer:latest /usr/bin/composer /usr/bin/composerLaravel用にnpmやcomposerも入るようにしています
Oracle instant client導入~OCI8のインストール部分は
LaraDockのworkspaceとphp-fpmのDockerfileに同様の設定をいれると動くと思います。
LaraDockでやりたい方はお試しあれ!/etc/hostsを変更
Windows10の場合はC:\Windows\System32\drivers\etc\hosts
管理者モードでメモ帳を起動して設定したホスト名を追記します。
これで http://project1.local/ でアクセスできるようになります。127.0.0.1 project1.local ::1 project1.local 127.0.0.1 project2.local ::1 project2.local起動
docker-compose up -dLaravelのインストールとOCI8設定
1.php-fpmに入ります
docker-compose exec php-fpm bash2.Laravelのインストール
$ cd /var/www <=設定したドキュメントルートに合うようにしてください $ composer create-project --prefer-dist laravel/laravel project1 "5.8.*" <=5.8の場合 $ composer create-project --prefer-dist laravel/laravel project1 <=最新版3.yajra/laravel-oci8のインストール
https://github.com/yajra/laravel-oci8
ドキュメント通りにLaravelのバージョンにあわせてcomposerでインストールします
Laravelのディレクトリに移動して$ composer require yajra/laravel-oci8:"5.8.*" <=Laravel5.8 $ composer require yajra/laravel-oci8:"^6.0" <=Laravel6~4.Laravelのconfig/app.phpのproviders内に追加します
config/app.php'providers' => [ // ... Yajra\Oci8\Oci8ServiceProvider::class, ],5.config/oracle.phpの作成
php artisan vendor:publish --tag=oracle6..env内のORACLEの設定
.envDB_CONNECTION=oracle DB_HOST=xxx.xxx.xxx.xxx DB_PORT=1521 DB_DATABASE=oracleのSID DB_USERNAME=xxx DB_PASSWORD=xxx以上でMySQLと同じようにDBの操作ができました。
リポジトリ
作成したOracle instant client本体なしの雛形リポジトリを置いておきます。
Docker初心者なのでここはこうしたほうがいいよと教えていただけると嬉しいです!
https://github.com/anissia0828/nginx_php73_oci参考にさせていただきました
- 投稿日:2020-02-04T17:51:51+09:00
MobileNetV2-SSDLiteのPascal-VOCデータセットによる学習 [Docker版リメイク]
1. Introduction
1年前に記事にしたMobileNetV2-SSDLiteのトレーニング環境構築記事を超簡易仕様にリメイクしました。 GPU対応版の最新のDockerが導入されている段階から作業に着手すると、15分ほどでトレーニングを開始できると思います。 ミスり要素はほぼ無いと思います。 学習が終わったらトレーニング済みモデル(.ckpt/.pb)の
Integer Quantizationを実施して Github へコミットする予定です。 トレーニング用データセットの前処理など、全ての処理はシェルスクリプト内に記載してありますので、気になる方はconstants.shあるいはprepare_checkpoint_and_dataset.shあるいはretrain_detection_model.shの内容をご覧ください。2. Environment
- Ubuntu 18.04 x86_64, RAM 16GB, Geforce GTX1070
- Tensorflow-GPU v1.15.2
- Docker 19.03.5
- Pascal VOC 2012/2007 Dataset
- MobileNetV2-SSDLite
3. Procedure
Creating_Docker_files$ DETECT_DIR=${HOME}/edgetpu/detection && mkdir -p $DETECT_DIR $ cd $DETECT_DIR && nano DockerfileDockerfile### Ubuntu 18.04 FROM tensorflow/tensorflow:1.15.2-gpu-py3 RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ protobuf-compiler python-pil python-lxml python-tk \ autoconf automake libtool curl make g++ unzip wget git nano \ libgflags-dev libgoogle-glog-dev liblmdb-dev libleveldb-dev \ libhdf5-serial-dev libhdf5-dev python3-opencv python-opencv \ python3-dev python3-numpy python3-skimage gfortran libturbojpeg \ python-dev python-numpy python-skimage python3-pip python-pip \ libboost-all-dev libopenblas-dev libsnappy-dev software-properties-common \ protobuf-compiler python-pil python-lxml python-tk libfreetype6-dev pkg-config \ libpng-dev libhdf5-100 libhdf5-cpp-100 # Get the tensorflow models research directory, and move it into tensorflow source folder to match recommendation of installation RUN git clone https://github.com/tensorflow/models.git && \ mkdir -p /tensorflow && \ mv models /tensorflow # Install the Tensorflow Object Detection API from here # https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md # Install object detection api dependencies RUN pip3 install Cython && \ pip3 install contextlib2 && \ pip3 install pillow && \ pip3 install lxml && \ pip3 install jupyter && \ pip3 install matplotlib && \ pip2 install Cython && \ pip2 install contextlib2 && \ pip2 install pillow && \ pip2 install lxml && \ pip2 install jupyter && \ pip2 install matplotlib # Get protoc 3.0.0, rather than the old version already in the container RUN curl -OL "https://github.com/google/protobuf/releases/download/v3.0.0/protoc-3.0.0-linux-x86_64.zip" && \ unzip protoc-3.0.0-linux-x86_64.zip -d proto3 && \ mv proto3/bin/* /usr/local/bin && \ mv proto3/include/* /usr/local/include && \ rm -rf proto3 protoc-3.0.0-linux-x86_64.zip # Install pycocoapi RUN git clone --depth 1 https://github.com/cocodataset/cocoapi.git && \ cd cocoapi/PythonAPI && \ make -j8 && \ cp -r pycocotools /tensorflow/models/research && \ cd ../../ && \ rm -rf cocoapi # Run protoc on the object detection repo RUN cd /tensorflow/models/research && \ protoc object_detection/protos/*.proto --python_out=. # Set the PYTHONPATH to finish installing the API ENV PYTHONPATH $PYTHONPATH:/tensorflow/models/research:/tensorflow/models/research/slim # Install wget (to make life easier below) and editors (to allow people to edit the files inside the container) RUN apt-get update && \ apt-get install -y wget nano ARG work_dir=/tensorflow/models/research # Get object detection transfer learning scripts. ARG scripts_link="http://storage.googleapis.com/cloud-iot-edge-pretrained-models/docker/obj_det_scripts.tgz" RUN cd ${work_dir} && \ wget -O obj_det_scripts.tgz ${scripts_link} && \ tar zxvf obj_det_scripts.tgz WORKDIR ${work_dir}Ctrl + O
Ctrl + XBuild_a_Docker_image$ docker build - < Dockerfile --tag training_containerStart_Docker_container$ docker run \ --runtime=nvidia \ --name training_container \ -it \ --privileged \ -p 6006:6006 \ training_container \ /bin/bashDownload_training_shell_script### Download constants.sh $ curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1e74pfaoHqp6WiWwTGamzN7wNRTDoR3q3" > /dev/null $ CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)" $ curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1e74pfaoHqp6WiWwTGamzN7wNRTDoR3q3" -o constants.sh ### Download prepare_checkpoint_and_dataset.sh $ curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1Rk2VRGBwZnlcfl3DmryPMbNpICJ2R-vr" > /dev/null $ CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)" $ curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1Rk2VRGBwZnlcfl3DmryPMbNpICJ2R-vr" -o prepare_checkpoint_and_dataset.sh ### Download retrain_detection_model.sh $ curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1MbjoqxBG56aDyvGxBbJd1QCbGo4nDKnm" > /dev/null $ CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)" $ curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1MbjoqxBG56aDyvGxBbJd1QCbGo4nDKnm" -o retrain_detection_model.sh
constants.sh
constants.sh#!/bin/bash declare -A ckpt_link_map declare -A ckpt_name_map declare -A config_filename_map ckpt_link_map["mobilenet_v2_ssdlite"]="http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz" ckpt_name_map["mobilenet_v2_ssdlite"]="ssdlite_mobilenet_v2_coco_2018_05_09" config_filename_map["mobilenet_v2_ssdlite-true"]="pipeline_mobilenet_v2_ssdlite_retrain_whole_model.config" INPUT_TENSORS='normalized_input_image_tensor' OUTPUT_TENSORS='TFLite_Detection_PostProcess,TFLite_Detection_PostProcess:1,TFLite_Detection_PostProcess:2,TFLite_Detection_PostProcess:3' OBJ_DET_DIR="$PWD" #rm -rf "${OBJ_DET_DIR}/learn" mkdir -p "${OBJ_DET_DIR}/learn" LEARN_DIR="${OBJ_DET_DIR}/learn" #rm -rf "${LEARN_DIR}/data" #rm -rf "${LEARN_DIR}/ckpt" #rm -rf "${LEARN_DIR}/train" #rm -rf "${LEARN_DIR}/models" mkdir -p "${LEARN_DIR}/data" mkdir -p "${LEARN_DIR}/ckpt" mkdir -p "${LEARN_DIR}/train" mkdir -p "${LEARN_DIR}/models" DATASET_DIR="${LEARN_DIR}/data" CKPT_DIR="${LEARN_DIR}/ckpt" TRAIN_DIR="${LEARN_DIR}/train" OUTPUT_DIR="${LEARN_DIR}/models"
prepare_checkpoint_and_dataset.sh
prepare_checkpoint_and_dataset.sh#!/bin/bash # Exit script on error. set -e # Echo each command, easier for debugging. set -x usage() { cat << END_OF_USAGE Downloads checkpoint and dataset needed for the tutorial. --network_type Can be one of [mobilenet_v1_ssd, mobilenet_v2_ssd], mobilenet_v1_ssd by default. --train_whole_model Whether or not to train all layers of the model. false by default, in which only the last few layers are trained. --help Display this help. END_OF_USAGE } network_type="mobilenet_v2_ssdlite" train_whole_model="true" while [[ $# -gt 0 ]]; do case "$1" in --network_type) network_type=$2 shift 2 ;; --train_whole_model) train_whole_model=$2 shift 2;; --help) usage exit 0 ;; --*) echo "Unknown flag $1" usage exit 1 ;; esac done source "$PWD/constants.sh" echo "PREPARING checkpoint..." mkdir -p "${LEARN_DIR}" ckpt_link="${ckpt_link_map[${network_type}]}" ckpt_name="${ckpt_name_map[${network_type}]}" cd "${LEARN_DIR}" rm -rf "${CKPT_DIR}/${ckpt_name}" wget -O "${CKPT_DIR}/${ckpt_name}.tar.gz" "$ckpt_link" tar -zxvf "${CKPT_DIR}/${ckpt_name}.tar.gz" -C "${CKPT_DIR}" rm "${CKPT_DIR}/${ckpt_name}.tar.gz" rm -rf "${CKPT_DIR}/saved_model" cp -r ${CKPT_DIR}/${ckpt_name}/* "${CKPT_DIR}/" echo "CHOSING config file..." cd "${OBJ_DET_DIR}" curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1IoHkfxfkXSUM8nnevrb_dVct72fMJ7t2" > /dev/null CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)" curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1IoHkfxfkXSUM8nnevrb_dVct72fMJ7t2" -o pipeline.config mv pipeline.config "${CKPT_DIR}" echo "REPLACING variables in config file..." sed -i "s%PATH_TO_BE_CONFIGURED/model.ckpt%${CKPT_DIR}/model.ckpt%g" "${CKPT_DIR}/pipeline.config" sed -i "s%PATH_TO_BE_CONFIGURED/mscoco_label_map.pbtxt%${DATASET_DIR}/pascal_label_map.pbtxt%g" "${CKPT_DIR}/pipeline.config" sed -i "s%PATH_TO_BE_CONFIGURED/mscoco_train.record%${DATASET_DIR}/pascal_train.record%g" "${CKPT_DIR}/pipeline.config" sed -i "s%PATH_TO_BE_CONFIGURED/mscoco_val.record%${DATASET_DIR}/pascal_val.record%g" "${CKPT_DIR}/pipeline.config" echo "PREPARING dataset" rm -rf "${DATASET_DIR}" mkdir -p "${DATASET_DIR}" cd "${DATASET_DIR}" # VOCtrainval_11-May-2012.tar <--- 1.86GB curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1rATNHizJdVHnaJtt-hW9MOgjxoaajzdh" > /dev/null CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)" curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1rATNHizJdVHnaJtt-hW9MOgjxoaajzdh" -o VOCtrainval_11-May-2012.tar # VOCtrainval_06-Nov-2007.tar <--- 460MB curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1c8laJUn-aaWEhE5NlDwIdNv5ZdogUAcD" > /dev/null CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)" curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1c8laJUn-aaWEhE5NlDwIdNv5ZdogUAcD" -o VOCtrainval_06-Nov-2007.tar # Extract the data. tar -xvf VOCtrainval_11-May-2012.tar && rm VOCtrainval_11-May-2012.tar tar -xvf VOCtrainval_06-Nov-2007.tar && rm VOCtrainval_06-Nov-2007.tar echo "PREPARING label map..." cd "${OBJ_DET_DIR}" cp "object_detection/data/pascal_label_map.pbtxt" "${DATASET_DIR}" echo "CONVERTING dataset to TF Record..." protoc object_detection/protos/*.proto --python_out=. python3 object_detection/dataset_tools/create_pascal_tf_record.py \ --label_map_path="${DATASET_DIR}/pascal_label_map.pbtxt" \ --data_dir=${DATASET_DIR}/VOCdevkit \ --year=merged \ --set=train \ --output_path="${DATASET_DIR}/pascal_train.record" python3 object_detection/dataset_tools/create_pascal_tf_record.py \ --label_map_path="${DATASET_DIR}/pascal_label_map.pbtxt" \ --data_dir=${DATASET_DIR}/VOCdevkit \ --year=merged \ --set=val \ --output_path="${DATASET_DIR}/pascal_val.record"
retrain_detection_model.sh
retrain_detection_model.sh#!/bin/bash # Exit script on error. set -e # Echo each command, easier for debugging. set -x usage() { cat << END_OF_USAGE Starts retraining detection model. --num_training_steps Number of training steps to run, 500 by default. --num_eval_steps Number of evaluation steps to run, 100 by default. --help Display this help. END_OF_USAGE } num_training_steps=200000 while [[ $# -gt 0 ]]; do case "$1" in --num_training_steps) num_training_steps=$2 shift 2 ;; --num_eval_steps) num_eval_steps=$2 shift 2 ;; --help) usage exit 0 ;; --*) echo "Unknown flag $1" usage exit 1 ;; esac done source "$PWD/constants.sh" python3 object_detection/model_main.py \ --pipeline_config_path="${CKPT_DIR}/pipeline.config" \ --model_dir="${TRAIN_DIR}" \ --num_train_steps="${num_training_steps}" \ --num_eval_steps="${num_eval_steps}"Granting_execution_authority_to_script_files$ chmod +x constants.sh $ chmod +x prepare_checkpoint_and_dataset.sh $ chmod +x retrain_detection_model.shData_preparation_and_Training### Data preparation $ ./prepare_checkpoint_and_dataset.sh ### Training $ NUM_TRAINING_STEPS=1000000 && \ NUM_EVAL_STEPS=100 && \ rm -rf learn/train && \ ./retrain_detection_model.sh \ --num_training_steps ${NUM_TRAINING_STEPS} \ --num_eval_steps ${NUM_EVAL_STEPS}check_the_progress_of_learning### Check learning status with Tensorboard $ docker exec -it training_container /bin/bash $ cd learn/train $ tensorboard --logdir=.Extract_files_from_Docker_container$ docker cp 07a048c6b1b8:/tensorflow/models/research/learn/train/model.ckpt-7044.data-00000-of-00001 . $ docker cp 07a048c6b1b8:/tensorflow/models/research/learn/train/model.ckpt-7044.index . $ docker cp 07a048c6b1b8:/tensorflow/models/research/learn/train/model.ckpt-7044.meta . $ docker cp 07a048c6b1b8:/tensorflow/models/research/learn/train/graph.pbtxt . $ docker cp 07a048c6b1b8:/tensorflow/models/research/learn/train/checkpoint .
- 投稿日:2020-02-04T17:47:10+09:00
Docker for windows環境にてPowershellでCtrl+zが使用できない問題の解決法(仮)
Docker for windows環境にてPowershellを使ってDocker上のLinuxをCUI操作している場合、Ctrl+zでLinuxにシグナルを送ろうとしても上手く動作しない。
Ctrl+zがPowershellの操作に割り当てられている様子。Linuxを抜けてPowershellの操作に戻ってしまう。
簡単な解決法として、Powershellで「レガシーコンソール」を使用することで解決した。プロパティから「レガシーコンソール」を選択するだけ
PowerShellのバー上で右クリック → プロパティを選択
これ以外のもっとエレガントな解決方法がきっとあるはずである。
参考:Windows PowerShell, Control-Z, and Kitematic
https://alankent.me/2017/07/04/windows-powershell-control-z-and-kitemati/
- 投稿日:2020-02-04T17:38:22+09:00
図解: Cluster APIを使ってKubernetesクラスタを作る (on Docker)
Cluster APIを使うと何ができるのか
Cluster APIとは、クラスタ管理を宣言的APIで実現するKubernetesプロジェクトです。
Quickstartを実行することで、Cluster APIの実現機能が把握できます。今回は、このQuickstartの流れを実機で試してみます。流れをまとめた次のような4コマ漫画を作りました。
1. 最初はManagement Clusterだけがあります。 2. Clusterを追加すると、クラスタが新規作成されますが、
中には何もありません。3. Machineを追加すると、マスターノードが追加されます。4. MachineDeploymentを追加すると、ワーカノード追加が追加されます。以下ではこの流れに沿って、手順を実行してみます。
環境
今回は、Docker Desktop for mac v2.2.0.0 がインストールされたMacbook Proで実施しました。その他以下がインストールされています。
kind1.17Management Clusterの準備
まずは4コマ漫画の1コマ目です。Cluster APIを持つクラスタ、Management Clusterを用意します。
最小限のKubernetesの準備
Cluster APIをインストールするには、Kubernetesクラスタが必要です。このクラスタをManagement Clusterといいます。クラスタを作る前にクラスタが必要というのは、少し手間なように感じます。でもAPIが利用できればよいので、マスターノードだけでかまいません。
ここでは、
kindというツールを使いマスターノード1台だけの最小限のクラスタを用意します。control-planeというのは、kindの設定でマスターノードと言う意味です。cat > kind-cluster-with-extramounts.yaml <<EOF kind: Cluster apiVersion: kind.sigs.k8s.io/v1alpha3 nodes: - role: control-plane extraMounts: - hostPath: /var/run/docker.sock containerPath: /var/run/docker.sock EOF kind create cluster --config ./kind-cluster-with-extramounts.yaml --name clusterapiCluster API のインストール
Cluster APIは、設定ファイルに相当するCRD (CustomResourceDefinition)と、その設定にしたがってクラスタを作成するcontroller-managerからなります。これらを一括でインストールします。
kubectl create -f https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.2.9/cluster-api-components.yaml namespace/capi-system created customresourcedefinition.apiextensions.k8s.io/clusters.cluster.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/machinedeployments.cluster.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/machines.cluster.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/machinesets.cluster.x-k8s.io created role.rbac.authorization.k8s.io/capi-leader-election-role created clusterrole.rbac.authorization.k8s.io/capi-manager-role created rolebinding.rbac.authorization.k8s.io/capi-leader-election-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/capi-manager-rolebinding created deployment.apps/capi-controller-manager created次に、実際の環境に合わせたブートストラップとプロバイダをインストールします。
今回は、Dockerだけの環境を使いますので、ブートストラップにKubeadmを、プロバイダにDocker用のものを使います。
以下の専用コンポーネントをインストールします。kubectl create -f https://github.com/kubernetes-sigs/cluster-api-bootstrap-provider-kubeadm/releases/download/v0.1.5/bootstrap-components.yaml namespace/cabpk-system created customresourcedefinition.apiextensions.k8s.io/kubeadmconfigs.bootstrap.cluster.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/kubeadmconfigtemplates.bootstrap.cluster.x-k8s.io created role.rbac.authorization.k8s.io/cabpk-leader-election-role created clusterrole.rbac.authorization.k8s.io/cabpk-manager-role created clusterrole.rbac.authorization.k8s.io/cabpk-proxy-role created rolebinding.rbac.authorization.k8s.io/cabpk-leader-election-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/cabpk-manager-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/cabpk-proxy-rolebinding created service/cabpk-controller-manager-metrics-service created deployment.apps/cabpk-controller-manager created kubectl get po -n cabpk-system NAME READY STATUS RESTARTS AGE cabpk-controller-manager-c58d8596f-rqczh 2/2 Running 0 7m13skubectl create -f https://github.com/kubernetes-sigs/cluster-api-provider-docker/releases/download/v0.2.1/provider-components.yaml namespace/capd-system created customresourcedefinition.apiextensions.k8s.io/dockerclusters.infrastructure.cluster.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/dockermachines.infrastructure.cluster.x-k8s.io created customresourcedefinition.apiextensions.k8s.io/dockermachinetemplates.infrastructure.cluster.x-k8s.io created role.rbac.authorization.k8s.io/capd-leader-election-role created clusterrole.rbac.authorization.k8s.io/capd-manager-role created clusterrole.rbac.authorization.k8s.io/capd-proxy-role created rolebinding.rbac.authorization.k8s.io/capd-leader-election-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/capd-manager-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/capd-proxy-rolebinding created service/capd-controller-manager-metrics-service created deployment.apps/capd-controller-manager created kubectl get po -n capd-system NAME READY STATUS RESTARTS AGE capd-controller-manager-7cd8c765c-84j7r 2/2 Running 0 5m22sこの時点で、
Docker上にはclusterapi-control-planeというコンテナ(Management cluster)が一つだけ動いています。docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 68d711500e26 kindest/node:v1.17.0 "/usr/local/bin/entr…" 11 minutes ago Up 11 minutes 127.0.0.1:32775->6443/tcp clusterapi-control-planeClusterAPIを使う
Cluster APIの以下のCRDを順に作成していきます。
ClusterMachineMachineDeployment
Cluster新規作成4コマ漫画の2コマ目になります。
Cluster APIで作るためのクラスタの設定ファイルを作成します。
cluster.yamlapiVersion: cluster.x-k8s.io/v1alpha2 kind: Cluster metadata: name: capi-quickstart spec: clusterNetwork: pods: cidrBlocks: ["192.168.0.0/16"] infrastructureRef: apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2 kind: DockerCluster name: capi-quickstart --- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2 kind: DockerCluster metadata: name: capi-quickstartkubectl create -f cluster.yaml cluster.cluster.x-k8s.io/capi-quickstart created dockercluster.infrastructure.cluster.x-k8s.io/capi-quickstart createdkubectl get dockercluster NAME AGE capi-quickstart 11s
Dockerを確認してみますと、以下のようにcapi-quickstart-lbというコンテナが起動していることがわかります。docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 38d5a9338e3d nginx:1.15.12-alpine "nginx -g 'daemon of…" 48 seconds ago Up 47 seconds 80/tcp, 40319/tcp, 0.0.0.0:40319->6443/tcp capi-quickstart-lb 68d711500e26 kindest/node:v1.17.0 "/usr/local/bin/entr…" 14 minutes ago Up 14 minutes 127.0.0.1:32775->6443/tcp clusterapi-control-plane
Machineを作る4コマ漫画の3コマ目になります。
MachineというCRDでマスターノードを作成します。machine.yamlapiVersion: cluster.x-k8s.io/v1alpha2 kind: Machine metadata: name: capi-quickstart-controlplane-0 labels: cluster.x-k8s.io/control-plane: "true" cluster.x-k8s.io/cluster-name: "capi-quickstart" spec: version: v1.15.3 bootstrap: configRef: apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfig name: capi-quickstart-controlplane-0 infrastructureRef: kind: DockerMachine apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2 name: capi-quickstart-controlplane-0 --- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2 kind: DockerMachine metadata: name: capi-quickstart-controlplane-0 --- apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfig metadata: name: capi-quickstart-controlplane-0 spec: initConfiguration: nodeRegistration: kubeletExtraArgs: eviction-hard: nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0% clusterConfiguration: controllerManager: extraArgs: enable-hostpath-provisioner: "true"kubectl create -f machine.yaml machine.cluster.x-k8s.io/capi-quickstart-controlplane-0 created dockermachine.infrastructure.cluster.x-k8s.io/capi-quickstart-controlplane-0 created kubeadmconfig.bootstrap.cluster.x-k8s.io/capi-quickstart-controlplane-0 created以下のようにmachineが起動されるまでにおおよそ10分かかりました。
kubectl get machines --selector cluster.x-k8s.io/control-plane NAME PROVIDERID PHASE capi-quickstart-controlplane-0 docker:////capi-quickstart-capi-quickstart-controlplane-0 running
Dockerでも以下のように、capi-quickstart-capi-quickstart-controlplane-0というコンテナが起動したことがわかります。docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f449784405e6 kindest/node:v1.15.3 "/usr/local/bin/entr…" About a minute ago Up About a minute 35547/tcp, 127.0.0.1:35547->6443/tcp capi-quickstart-capi-quickstart-controlplane-0 38d5a9338e3d nginx:1.15.12-alpine "nginx -g 'daemon of…" 11 minutes ago Up 11 minutes 80/tcp, 40319/tcp, 0.0.0.0:40319->6443/tcp capi-quickstart-lb 68d711500e26 kindest/node:v1.17.0 "/usr/local/bin/entr…" 25 minutes ago Up 25 minutes 127.0.0.1:32775->6443/tcp clusterapi-control-plane作成したクラスタにアクセスする
kubeconfigを作る
kubectlでクラスタ内に接続するために、kubeconfigファイルを作成します。予めcluster作成時に以下のようなSecretが作成されているので、そこから抜き出します。kubectl --namespace=default get secret/capi-quickstart-kubeconfig -o json \ | jq -r .data.value \ | base64 --decode \ > ./capi-quickstart.kubeconfig今回はMacbook上で実行したために、以下のコマンドで一部だけ変更します(
clusterの宛先と接続方法insecure-skip-tls-verifyを変更します。)sed -i -e "s/server:.*/server: https:\/\/$(docker port capi-quickstart-lb 6443/tcp | sed "s/0.0.0.0/127.0.0.1/")/g" ./capi-quickstart.kubeconfig # Ignore the CA, because it is not signed for 127.0.0.1 sed -i -e "s/certificate-authority-data:.*/insecure-skip-tls-verify: true/g" ./capi-quickstart.kubeconfig生成した
kubeconfigはこうなっています。capi-quickstart.kubeconfigapiVersion: v1 clusters: - cluster: insecure-skip-tls-verify: true server: https://127.0.0.1:40319 name: capi-quickstart contexts: - context: cluster: capi-quickstart user: kubernetes-admin name: kubernetes-admin@capi-quickstart current-context: kubernetes-admin@capi-quickstart kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: LS0tLS1CR... client-key-data: LS0t...この
kubeconfigを使ってkubectlを実行してみます。kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes NAME STATUS ROLES AGE VERSION capi-quickstart-capi-quickstart-controlplane-0 NotReady master 8m35s v1.15.3まずはMasterノードが動いていることがわかります。ただし、状態はまだ
NotReadyです。クラスタ内ネットワークが構築されていないためです。クラスタ内ネットワークを構築する
次に、ネットワークを構築します。
calicoをインストールします。kubectl --kubeconfig=./capi-quickstart.kubeconfig \ apply -f https://docs.projectcalico.org/v3.8/manifests/calico.yaml configmap/calico-config created customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created clusterrole.rbac.authorization.k8s.io/calico-node created clusterrolebinding.rbac.authorization.k8s.io/calico-node created daemonset.apps/calico-node created serviceaccount/calico-node created deployment.apps/calico-kube-controllers created serviceaccount/calico-kube-controllers createdkubectl --kubeconfig=./capi-quickstart.kubeconfig \ -n kube-system patch daemonset calico-node \ --type=strategic --patch=' spec: template: spec: containers: - name: calico-node env: - name: FELIX_IGNORELOOSERPF value: "true" ' daemonset.extensions/calico-node patchedこれを実行することにより、マスターノードは
Ready状態となります。Workerを追加する
4コマ漫画の最後のコマになります。ワーカーノードを
MachineDeploymentを使って追加します。以下の
worker.yamlファイルを作成し、Management Clusterに対しkubectl createコマンドを実行します。worker.yamlapiVersion: cluster.x-k8s.io/v1alpha2 kind: MachineDeployment metadata: name: capi-quickstart-worker labels: cluster.x-k8s.io/cluster-name: capi-quickstart # Labels beyond this point are for example purposes, # feel free to add more or change with something more meaningful. # Sync these values with spec.selector.matchLabels and spec.template.metadata.labels. nodepool: nodepool-0 spec: replicas: 1 selector: matchLabels: cluster.x-k8s.io/cluster-name: capi-quickstart nodepool: nodepool-0 template: metadata: labels: cluster.x-k8s.io/cluster-name: capi-quickstart nodepool: nodepool-0 spec: version: v1.15.3 bootstrap: configRef: name: capi-quickstart-worker apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfigTemplate infrastructureRef: name: capi-quickstart-worker apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2 kind: DockerMachineTemplate --- apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2 kind: DockerMachineTemplate metadata: name: capi-quickstart-worker spec: template: spec: {} --- apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfigTemplate metadata: name: capi-quickstart-worker spec: template: spec: # For more information about these values, # refer to the Kubeadm Bootstrap Provider documentation. joinConfiguration: nodeRegistration: kubeletExtraArgs: eviction-hard: nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0% clusterConfiguration: controllerManager: extraArgs: enable-hostpath-provisioner: "true"kubectl create -f worker.yaml machinedeployment.cluster.x-k8s.io/capi-quickstart-worker created dockermachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-worker created kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/capi-quickstart-worker createddocker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e6162d760dd7 kindest/node:v1.15.3 "/usr/local/bin/entr…" 2 minutes ago Up 2 minutes capi-quickstart-capi-quickstart-worker-85cbf8fd8c-mhrlz f449784405e6 kindest/node:v1.15.3 "/usr/local/bin/entr…" 16 minutes ago Up 16 minutes 35547/tcp, 127.0.0.1:35547->6443/tcp capi-quickstart-capi-quickstart-controlplane-0 38d5a9338e3d nginx:1.15.12-alpine "nginx -g 'daemon of…" 26 minutes ago Up 26 minutes 80/tcp, 40319/tcp, 0.0.0.0:40319->6443/tcp capi-quickstart-lb 68d711500e26 kindest/node:v1.17.0 "/usr/local/bin/entr…" 40 minutes ago Up 40 minutes 127.0.0.1:32775->6443/tcp clusterapi-control-planekubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes ✔ 1656 01:13:19 NAME STATUS ROLES AGE VERSION capi-quickstart-capi-quickstart-controlplane-0 Ready master 20m v1.15.3 capi-quickstart-capi-quickstart-worker-85cbf8fd8c-mhrlz Ready <none> 6m30s v1.15.3Workerを増やす
オプションで、
MachineDeploymentを編集することで動的にワーカーノードを追加することができます。以下では、1台だったワーカーノードを2台に増やします。
$ kubectl edit machinedeployment capi-quickstart-worker以下の行を変更します。
- replica: 1 + replica: 2保存して終了します。
Machineが以下のように増えています。$ kubectl get machines NAME PROVIDERID PHASE capi-quickstart-controlplane-0 docker:////capi-quickstart-capi-quickstart-controlplane-0 running capi-quickstart-worker-85cbf8fd8c-mhrlz docker:////capi-quickstart-capi-quickstart-worker-85cbf8fd8c-mhrlz running capi-quickstart-worker-85cbf8fd8c-wjk9h provisioningDockerコンテナを見ても、以下のように追加されます。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e55a1192feeb kindest/node:v1.15.3 "/usr/local/bin/entr…" About a minute ago Up About a minute capi-quickstart-capi-quickstart-worker-85cbf8fd8c-wjk9h e6162d760dd7 kindest/node:v1.15.3 "/usr/local/bin/entr…" 3 days ago Up 3 days capi-quickstart-capi-quickstart-worker-85cbf8fd8c-mhrlz f449784405e6 kindest/node:v1.15.3 "/usr/local/bin/entr…" 3 days ago Up 3 days 35547/tcp, 127.0.0.1:35547->6443/tcp capi-quickstart-capi-quickstart-controlplane-0 38d5a9338e3d nginx:1.15.12-alpine "nginx -g 'daemon of…" 3 days ago Up 3 days 80/tcp, 40319/tcp, 0.0.0.0:40319->6443/tcp capi-quickstart-lb 68d711500e26 kindest/node:v1.17.0 "/usr/local/bin/entr…" 3 days ago Up 3 days 127.0.0.1:32775->6443/tcp clusterapi-control-plane
kubectl get nodesコマンドでも確認できます。$ kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes NAME STATUS ROLES AGE VERSION capi-quickstart-capi-quickstart-controlplane-0 Ready master 3d22h v1.15.3 capi-quickstart-capi-quickstart-worker-85cbf8fd8c-mhrlz Ready <none> 3d22h v1.15.3 capi-quickstart-capi-quickstart-worker-85cbf8fd8c-wjk9h Ready <none> 3m8s v1.15.3上記のように、
capi-quickstart-capi-quickstart-worker-85cbf8fd8c-xxxxxの名前のノードが2台に増えたことが確認できました。まとめ
Cluster APIを使ってManagement ClusterからKubernetesクラスタを作ってみました。
宣言的APIで動的にワーカーノードを追加することができ、kindよりも柔軟性が高いと感じました。
ただし、Kubeadmの設定があまり隠蔽されないため、YAMLファイルを書く行数はkindより多くなっていると思います。
注意点として、頻繁にkubectlを実行するのですが、今自分がManagement Clusterにkubectlを打っているのか、はたまた作成後のKubernetesクラスタにkubectlを打っているのか、混乱しないように進める必要があると思いました。
- 投稿日:2020-02-04T17:35:55+09:00
Ubuntu に Docker + MySQL を入れる
Ubuntu に Docker + MySQL を入れてみる
Ubuntu の環境は既に作成済なのが前提
express と接続して中身見れるようにするのは次回
- PC環境
- Vagrant 2.2.7
- VirtualBox 6.1.2
- Ubuntu 18.04
- ここに Docker-CE + MySQL を入れていく
- 便利なので Docker-Compose も使うよ
Docker をインストールする
参考サイトを見ながらやれば、特に引っ掛からないはず。
Docker インストール前準備
# apt更新 $ sudo apt-get update # aptがHTTPS経由でリポジトリを使用できるようにする $ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common # Docker公式GPGキー追加 $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # キーを確認 $ sudo apt-key fingerprint 0EBFCD88 # stable設定 $ sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"Docker インストール
# apt更新 $ sudo apt-get update # 最新バージョンをインストール $ sudo apt-get install docker-ceDocker インストール後の話
# docker グループを作成する $ sudo groupadd docker # ユーザを docker グループに追加する $ sudo usermod -aG docker $USER # 再起動してグループメンバーシップを認識させる $ sudo reboot# sudo なしで docker が動くのを確認 $ docker run hello-world↓こんなのが出ます。タイミングとかで Digest が変わったりとかはするかも。
Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/Docker-Compose をインストールする
出来るだけ最新の方がいいかも。
最新は、Docker compose release pageにある。
今は、 1.25.4 が最新?# 最新をダウンロード $ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 実行権限を付与 $ sudo chmod +x /usr/local/bin/docker-compose # インストール確認 $ docker-compose --versionインストール確認すると↓のような出力が出る。
docker-compose version 1.25.4, build 8d51620aMySQL をインストールする
簡単に試す1
参考サイト->https://qiita.com/astrsk_hori/items/e3d6c237d68be1a6f548
公式のmysqlイメージがあるので、↓これだけで使えるみたいdocker pull mysql docker run --name mysql -e MYSQL_ROOT_PASSWORD=mysql -d -p 3306:3306 mysql簡単に試す2
参考サイト->https://budougumi0617.github.io/2018/05/20/create-instant-mysql-by-docker/
途中までは読めたけどまだ分かんないから後でちゃんと読む簡単だけど簡単じゃない方?
ちゃんと自分でDBを作成してテーブルを作る
参考サイト->https://qiita.com/tiwu_official/items/9ffc8e1fd1173b1a9e40
細かく試した話は後で追記します参考
- Dockerの話
- Docker公式の話
- Docker compose release page
- MySQLの話
- MySQL, Redisを利用する開発環境を Docker CE で構築する
- 投稿日:2020-02-04T16:59:12+09:00
kubeadmを使用したKubernetes環境構築
Kubermetes1.17環境をkubeadm(環境構築ツール)を用いて作成していく。
過去何度かkubeadmで環境をセットアップしてきたが、躓くことが多いため
備忘録としても活用していきたい。1.前提となる環境の作成(UbuntuにDockerインストール)
2.MasterNode、Workerノードの構築
3.MasterNodeのセットアップ
4.WorkerNodeのジョイン
5.最後に1.前提となる環境の作成
Kubernetesをセットアップする前に、ゲストOSの準備やDockerのインストールが必要になるので、それらを準備する。
【Virtualbox】仮想マシン作成
今回、仮想化ソフト:VertualBox、ゲストOS:Ubuntu18.04.3 LTS上でKubernetes環境を構築していく。
まずはホストOSにVirtualBoxをインストールする。
インストール手順は以下を参照
https://eng-entrance.com/virtualbox-installインストールが完了したら、ゲストOSとなるUbuntuのisoファイルを取得する必要がある。以下のサイトから64-bit PC (AMD64) desktop imageのisoファイルをダウンロードする。
http://releases.ubuntu.com/18.04/VirtualBoxを起動させて、「新規(N)」をクリックする。
以下を設定後、作成をクリックする。
・名前:任意(MasterNodeならMaster、WorkerNodeならWorkerなど、、、)
・タイプ(Linux)
・Ubuntu(64-bit)
「仮想ハードディスクの作成」は設定変更せず「作成」をクリックする。
(今後アプリなどをデプロイしていく場合は容量を追加したほうが◎)
作成後、以下のように仮想マシンが作成されていることを確認し、
「設定(S)」をクリックする。
「システム」→「プロセッサー(P)」でプロセッサー数(P)を2に変更する。
「ストレージ」で「コントローラー:IDE」下の空のディスクにダウンロードした
isoファイルを割り当て、「OK」をクリックする。※「属性」欄のディスクマークをクリックすることで割り当てるファイルを選択することができる。
ここまでの作業が完了したら、作成した仮想マシンを選択した状態で「起動(T)」をクリックする。※起動したUbuntuに対する初期設定の変更などは特になし。
Dockerインストール
実際に仮想マシンにDockerをインストールする。
まずはお決まりのアップデートを実施する。$sudo apt update $sudo apt upgrade前提ソフトウェアのインストール、docker公式のGPG公開鍵をインストール
$sudo apt install apt-transport-https ca-certificates curl software-properties-common $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -aptリポジトリの設定の設定。
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"docker-ceのインストール。
$sudo apt-get update $sudo apt-get install docker-ceインストール完了後、docker runコマンドでhello-worldコンテナを実行し、
以下のように出力されれば問題なし。(実行結果は一部割愛)$sudo docker run hello-world nable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: ・・・・ここまでをMasterNode、WorkerNode合わせて準備しておく。
2.MasterNode、Workerノードの構築
ここからKubermetesをインストールしていくための作業に入る。
また、以下の作業はMasterNode、WorkerNode共通の作業となる。Kubernetesのキーを取得
$curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -Kubernetesのリポジトリを登録した後、更新を実行する。
$sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main" $sudo apt-get updateswapをオフにする。
sudo swapoff -a各パッケージをインストールする。
apt-get install -y kubelet kubeadm kubectlパッケージインストール後、/etc/systemd/system/kubelet.service.d/10-kubeadm.confに以下を追記する。
$vi 10-kubeadm.conf Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs"上記を実行することで、Cgroup DriverをDockerとkubeletとの間で一致させている。※この作業を実行しないと、MasterNodeのセットアップ時や、WorkerNodeのjoin時にエラーが出力される。(対処にはkubeadmのresetが必要)
3.MasterNodeのセットアップ
MasteNodeの初期化(init)を実行する。
podネットワークプロバイダにflannelを使用するため、 --pod-network-cidr=10.244.0.0/16を指定する。$ kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=<kube-apiserverがリクエストを待ち受けるIPアドレス>実行後、以下が表示されればMasterNodeの初期化は成功となる。
Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join XXX.XXX.XXX.XXX:6443 --token 7jpywr.uck1h30a1r9rfh2s \ --discovery-token-ca-cert-hash sha256:18cfec05b9caac750cee77fb162db5f675db3f5ea2031da2030caa209e2eee06この際、表示されている「kubeadm join~」の値は後程使用するので、メモしておくこと。
以下コマンドを実行する。
$mkdir -p $HOME/.kube $sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $sudo chown $(id -u):$(id -g) $HOME/.kube/configMasterNodeの状態を確認する。
(STATUSはNotReadyで問題ない)$kubectl get nodes NAME STATUS ROLES AGE VERSION master-virtualbox NotReady master 5h6m v1.17.2flannelのインストール前にiptablesを編集する。
sudo sysctl net.bridge.bridge-nf-call-iptables=1flannelをインストールする。
$kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.ymlノードの状態を確認し、「Ready」になっていればセットアップは完了。
$kubectl get nodes NAME STATUS ROLES AGE VERSION master-virtualbox Ready master 5h6m v1.17.24.WorkerNodeのジョイン
workerNodeにてMasterNodeのinit時に発行されたコマンド(kubeadm join~)を実行する。
$kubeadm join XXX.XXX.XXX.XXX:6443 --token 7jpywr.uck1h30a1r9rfh2s --discovery-token-ca-cert-hash sha256:18cfec05b9caac750cee77fb162db5f675db3f5ea2031da2030caa209e2eee06実行後、以下が表示されればMasterNodeへの追加が完了となる。
This node has joined the cluster: * Certificate signing request was sent to apiserver and a response was received. * The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the control-plane to see this node join the cluster.時間が経過すると、トークンが無効になるので以下コマンドで再発行を適宜実施する。
#token $kubeadm token create#discovery-token-ca-cert-hash $openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'MasterNodeでクラスタに参加しているか確認する。
$kubectl get nodes NAME STATUS ROLES AGE VERSION master-virtualbox Ready master 5h6m v1.17.2 node-virtualbox Ready <none> 5h4m v1.17.2MasterNodeでROLESのラベルを編集する。(MasterNode、WorkerNodeがわかるように)
$kubectl label node node-virtualbox node-role.kubernetes.io/node= $kubectl get nodes NAME STATUS ROLES AGE VERSION master-virtualbox Ready master 5h6m v1.17.2 node-virtualbox Ready node 5h4m v1.17.25.最後に
kubeadmの構築は簡単そうに見えてとにかく穴が多い。。。
(特にMasterの初期化、Workerのjoin)
今後もKubernetesのアップデートの度に何かしら手順が変わったりすると思うので、アンテナを張っておかないと、、、参考文献
Ubuntu 18.04 LTS にKubernetes環境をインストールする [Master / Worker]
- 投稿日:2020-02-04T16:17:07+09:00
AWS EC2 Amazon Linux 2 + Docker + Jenkins
概要
AWSのEC2(Amazon Linux2)でDockerでJenkins環境を構築する
Dockerのインストール
$ sudo yum install -y docker $ sudo service docker start自動起動を有効にする
$ sudo systemctl enable dockerdocker imageのダウンロード
$ sudo docker pull jenkins/jenkins:ltsdocker imageの起動
$ sudo docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts初期パスワード
先ほどのコマンド実行すると↓みたいなのが出力されるのでメモしておく
************************************************************* ************************************************************* ************************************************************* Jenkins initial setup is required. An admin user has been created and a password generated. Please use the following password to proceed to installation: {パスワードがここに表示される} This may also be found at: /var/jenkins_home/secrets/initialAdminPassword ************************************************************* ************************************************************* *************************************************************ブラウザアクセス
http://{IP}:8080/
ログイン
Administrator passwordに先ほどメモっといたパスワードを入力すれば完了
以降の作業は参考資料を見てもらえればと思います。
おわり
参考資料
- 投稿日:2020-02-04T15:36:53+09:00
Docker 環境で nodemon が watch してくれない問題と対処方法
Web アプリの開発環境を Docker で作っていたところ、nodemon がうまくファイル変更を検出してくれなくて困ったので、そのときのメモ。
マウントしたボリュームだと nodemon が watch してくれない問題
問題を再現するために、以下の3つのファイルを用意する。
ポイントとしては、ホストのディレクトリをコンテナ内にマウントしてそれをコンテナ内の nodemon が watch しているということ。
DockerfileFROM node:12 ADD . /app WORKDIR /app CMD ["node", "."]index.jsconst http = require('http') http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('ok') }).listen(80)docker-compose.ymlversion: '3' services: app: build: . ports: - 8080:80 volumes: - .:/app command: npx nodemon
docker-compose upでコンテナを起動し、Web ブラウザからhttp://localhost:8080/にアクセスするとokと表示されるはず。この開発用コンテナは nodemon から node プロセスを起動しているので、
index.jsが編集された場合には自動で restart してほしい。しかしこの場合、いくら
index.jsを編集しても nodemon はその変更を検出してくれない。Chokidar が Polling するように設定する
nodemon はファイル監視のために内部で Chokidar を利用しており、そのドキュメントにはこのように書いてある。
usePolling (default: false). Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU utilization, consider setting this to false. It is typically necessary to set this to true to successfully watch files over a network, and it may be necessary to successfully watch files in other non-standard situations. Setting to true explicitly on MacOS overrides the useFsEvents default. You may also set the CHOKIDAR_USEPOLLING env variable to true (1) or false (0) in order to override this option.
ネットワーク経由でファイルを監視する場合にはポーリングするように設定する必要があるらしい。
docker-compose.yml+ environment: + CHOKIDAR_USEPOLLING: 1というわけで環境変数
CHOKIDAR_USEPOLLING=1を設定した上で再試行したところ、無事にファイル変更を検出してくれるようになった。めでたしめでたし。
- 投稿日:2020-02-04T14:19:44+09:00
MySQL の Docker コンテナで実行した SQL の履歴を保持する
MySQL クライアントの
mysqlコマンドで実行した SQL は、~/.mysql_hisotryというファイルに保存されるのですが、docker-compose downとかしてコンテナを削除すると、当然このファイルも消えてしまい、履歴が消えてしまいます。
これでは不便なので、ホスト側にファイルを書き込むようにして、毎回これをマウントする方法を考えました。まずホスト側に
.mysql_historyを保存するディレクトリを作ります。
名前や場所はなんでも構いません。$ mkdir -p docker/mysql/history次にこれをマウントし、環境変数
MYSQL_HISTFILEで.mysql_historyの保存先を変更します。
マウント先もファイル名も、MYSQL_HISTFILEでパスさえ指定できれば、どこでも構いません。$ docker run --rm -e MYSQL_HISTFILE=/root/.config/mysql/.mysql_hisotry -v ${PWD}/docker/mysql/history:/root/.config/mysql mysql
docker-compose.ymlの場合はこんな感じ。version: '3' services: mysql: container_name: mysql image: mysql restart: always volumes: - ./docker/mysql/data:/var/lib/mysql - ./docker/mysql/history:/root/.config/mysql # ← これと environment: MYSQL_HISTFILE: /root/.config/mysql/.mysql_hisotry # ← これやってみると簡単だけど、ググってもあまり情報が見付からなかったのでメモでした。
- 投稿日:2020-02-04T12:18:17+09:00
docker exec で ヒアドキュメントを使いたいんじゃ
タイトルのような状況に遭遇してしまった場合
以下のように実行する。
$ docker exec -i postgres /usr/local/bin/psql db -U db_user <<EOT select version(); EOT version --------------------------------------------------------------------------------------- PostgreSQL 11.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 8.2.0) 8.2.0, 64-bit (1 row)ヒアドキュメントを入力とするので -t オプション(疑似TTYの割り当て)は不要
つけた場合はエラーになる。$ docker exec -it postgres /usr/local/bin/psql db -U db_user <<EOT select version(); EOT the input device is not a TTY以下のように sh -c で実行することもできる。
$ docker exec -it postgres sh -c "/usr/local/bin/psql db -U db_user <<EOT select version(); EOT" version --------------------------------------------------------------------------------------- PostgreSQL 11.2 on x86_64-pc-linux-musl, compiled by gcc (Alpine 8.2.0) 8.2.0, 64-bit (1 row)
- 投稿日:2020-02-04T12:15:40+09:00
Docker導入 windows10 pro
Raspberry Piを用いて機械学習モデルを動かしたいと考えています。おそらくDockerを扱うことになるのですが、そもそもDockerで何ができるのか、何が便利なのかを知る必要があるので、実際にDockerを使ってみることで理解を深めようと思います。
※この記事は学習が進み次第再び編集を行います。
Dockerの導入
- windows10 homeだったのでHyper-Vの仮想化機能のついたwindows10 proにアップグレードしました。13824円かかります。アップグレードは5分もかからず終了!
- スタートボタンを右クリックしタスクマネージャを開き、パフォーマンスタブで仮想化が有効になっているか確認
- https://hub.docker.com/editions/community/docker-ce-desktop-windows を開き、ログインしてDockerをダウンロード
Docker基礎
いくつか用語の確認をします。
Dockerイメージ
Dockerコンテナを構成するOSやファイルシステム、実行するアプリケーションや設定をまとめたもので、コンテナを作成するために利用されるテンプレートとなるもの
Dockerコンテナ
Dockerイメージを元に作成され、具現化されたファイルシステムとアプリケーションが実行されている状態
要するにDockerイメージからコンテナが作られ、コンテナの中でOSとして構成されたファイルシステム、アプリが実行されるということです。
主なdocker コマンド
docker container ls -q
コンテナの一覧表示
docker ls
動いているコンテナの確認
docker ls -a
停止しているコンテナの確認
docker rm [コンテナID]
コンテナの削除
docker images
イメージの確認
docker rmi [イメージID]
イメージの削除
docker --help
helpの閲覧ex.
docker image --helpでimageコマンドのhelpが閲覧できる
docker image build -t イメージ名[:タグ名] Dockerfile配置ディレクトリのパス
イメージをビルドする(イメージを構築するという意味) -t (タグ付け)はほぼ必須
docker container ls --filter "[イメージ名]" -q
ancestorで指定したイメージから作られたコンテナを表示することができます
docker stop [コンテナID]
コンテナの停止
docker container ls --filter "[イメージ名]" -q | % { docker stop $_ }
filterでコンテナIDを取得し、パイプラインでdocker stopに渡します
docker run -d -p [イメージ名]
コンテナの実行。-dはdetachの略で、バックグラウンド実行を行う。-pはpublichの略で、portを指定する。左の数字がホストからの接続ポートで、右の数字がコンテナ側への接続ポートを表す参考文献
- Docker/Kubernetes 実践コンテナ開発入門
- https://stackoverflow.com/questions/48813286/stop-all-docker-containers-at-once-on-windows
- 投稿日:2020-02-04T12:04:56+09:00
コード書いたことないPdMやPOに捧ぐ、Rails on Dockerハンズオン vol.2 -Hello, Rails on Docker-
この記事はなにか?
この記事は私が社内のプログラミング未経験者、ビギナー向けに開催しているRuby on Rails on Dockerハンズオンの内容をまとめたものです。ていうかこの記事を基にそのままハンズオンします。ハンズオンは
1回の内容は喋りながらやると大体40~50分くらいになっています。お昼休みに有志でやっているからです。
現在進行形なので週1ペースで記事投稿していけるように頑張ります。
ビギナーの方のお役にたったり、同じように有志のハンズオンをしようとしている人の参考になれば幸いです。
$,#,>について
$: ローカルでコマンドを実行するときは、頭に$をつけています。
#: コンテナの中でコマンドを実行するときは、頭に#をつけています。
>: Rails console内でコマンド(Rubyプログラム)を実行するときは、頭に>をつけています。
はじめに
第二回目の今回は、Ruby on RailsをDockerコンテナで起動させるHello worldをやっていきます。
今日のゴール
- Ruby on Rails on Docker で Hello world する
では早速、Ruby on Rails on Docker で Hello world していきましょう!
Hello, Ruby on Rails on Docker
今回は↓の図のように、Docker 上に Rails アプリケーション用のコンテナと PostgreSQL (database) 用のコンテナを作っていきます。
まず、作業用のディレクトリを作っておきましょう。$ mkdir Handson $ cd Handson今後、この
Handsonディレクトリをホームディレクトリとして話を進めますので、特に指定がない場合、Handsonディレクトリでコマンドを叩いたり、Handsonディレクトリから見た相対パスでファイルを編集していると思ってください。では早速、Ruby on Rails on Docker な環境を構築するために以下の4つのファイルを作成していきます。
Dockerfile: Rails アプリ用の Docker image の元となる設計図Gemfile: Rails アプリに必要なgemを記載するファイルGemfile.lock:Gemfileによってインストールされたgemのバージョン情報などを管理するファイルdocker-compose.yml: 今回のアプリをコンテナ起動させるための Dcoker Compose ファイルDockerfile
DockerfileFROM ruby:2.7.0-alpine3.11 ENV HOME="/app" ENV LANG=C.UTF-8 ENV TZ=Asia/Tokyo WORKDIR $HOME RUN apk update && \ apk upgrade && \ apk add --no-cache \ gcc \ g++ \ libc-dev \ libxml2-dev \ linux-headers \ make \ nodejs \ postgresql \ postgresql-dev \ tzdata \ yarn && \ apk add --virtual build-packs --no-cache \ build-base \ curl-dev COPY Gemfile $HOME COPY Gemfile.lock $HOME RUN bundle install && \ apk del build-packs COPY . $HOME EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0"]Dockerfile は初めて見る人にとっては「なんだこれ?」なものな気がしますが、読んでみると意外とシンプルです。
頭に大文字で書かれているのが命令と呼ばれるものでコマンドみたいなものです。
今回の Dockerfile では以下の命令を利用しています。
FROM: ベースイメージを定義する命令です。ruby イメージを指定しているので、元々 Ruby を使用できるイメージの上に Rails を動かす環境を作っていきます。タグの2.7.0-alpine3.11は2020.02.02時点で Ruby の最新バージョンを軽量ディストリビューションとしておなじみの alpine linux のこれまた最新バージョン3.11上で動かしているものを選んでいます。ENV: 環境変数を定義する命令です。WORKDIR: 作業ディレクトリを定義する命令です。ベースイメージ内に該当のディレクトリがない場合は、そのディレクトリを作成することもしてくれます。COPY: ホストのファイルやディレクトリをイメージ内にコピーする命令です。RUN: コマンドを実行する命令です。EXPOSE: コンテナがリッスンするポートを宣言する命令です。 Rails ではデフォルトで 3000 番ポートを使用するので 3000 を指定してあげています。CMD: ソフトウェアを実行するためのコマンドを定義する命令です。コンテナが起動する時に実行されるコマンドといった方がイメージ湧きやすいかもしれません。少し特別な書き方(["xxx", "xxx"]みたいな)をしますが、Rails アプリケーションを起動させるコマンドはrails server -b 0.0.0.0でして、それをCMDの記法で書いています。あらかた命令と1行1行の内容について述べてしまいましたが、取りこぼしているところをキャッチアップ。
RUN宣言でapk ~と色々書いている9行目からの部分がありますが、apk addは Alpine linux でパッケージをインストールするコマンドです。
apk updateでパッケージリポジトリの最新のインデックス(インストールできる最新バージョンは何か)を取得してきて、apk upgradeですでにインストールしているパッケージで最新版にアップデートできるものをアップデートします。その後、apk addで Rails を起動するのに必要なパッケージをインストールしていきます。--no-cacheオプションはキャッシュを残さないようにするためのオプションです。不要なキャッシュを残さないことでコンテナ自体を軽量に保つことができます。(コンテナは軽量に保っておいた方がダウンロードに時間がかからなかったり、ホストのボリュームを圧迫しないのでよいとされています。)--virtualオプションはそのインストールしたパッケージ達を一つのグループとして名前づけしています。今回の例だとbuild-packsという名前をつけています。ここでインストールしたパッケージは Rails をビルドする上では必要なのですが起動させるためには不要なのであとでapk delで削除するために名前づけしています。その後、
COPY命令でGemfile、Gemfile.lockをイメージ内にコピーして、bundle installを実行してます。bundle installはGemfileの内容に沿ってgemをインストールするコマンドです。Rails 自体もgemでインストールできるのでGemfileにrailsを記入しておけばこのbundle installの際にインストールされます。Gemfile.lockはすでにインストール済のgemのバージョンなどを管理して無闇にバージョンアップさせないようにしてくれます。最後に
COPY . $HOMEでローカルホストのファイルを一式イメージ内にコピーすることで Rails アプリケーションを起動させられる Docker image を作ることができます。Gemfile
Gemfilesource 'https://rubygems.org' gem 'rails', '~>6'Gemfileはかなりシンプルで、インストールする
gemのソースとrailsgem をインストールすることを定義しています。Rails は2020.02.02時点で最新バージョンが 6.0.2 なのでまぁメジャーバージョンとして 6 のものをインストールしてくださいというような指定の仕方をしています。
Rails アプリケーションでは最初rails newコマンドでアプリに必要なgemやファイルをインストール・生成するため、初期ではこれほどシンプルなGemfileがあるだけで構わないのです。
Gemfileでバージョンを指定する表現方法はいくつかあります。gemはGitHubなどで公開されていることが多くて大体 README でこう Gemfile に記載してくれと書かれていることが多いのであんまり気にすることはないかもしれませんが一応紹介。
gem 'rails', '6.0.0': 絶対 6.0.0 をインストール(バージョンを定義)gem 'rails', >= 6.0.0': 6.0.0 より最新のものをインストール(最低バージョンを定義)gem 'rails', >= 6.0.0', < 6.0.2: 6.0.0 以上 6.0.2 未満のバージョンをインストール(バージョンの範囲を定義)gem 'rails', '~> 6.0.0': 6.0.X のバージョンをインストール(マイナーバージョンを定義)Gemfile.lock
Gemfile.lockは最初にbundle installされるときに書き込まれるので、最初は空ファイルで問題ありません。$ touch Gemfile.lock
touchコマンドはファイルの更新日時を現在時刻に更新するためのコマンドですが、ファイルが存在しない場合は空ファイルを生成してくれるのでGemfile.lockを生成するために使いました。docker-compose.yml
docker-compose.ymlversion: '3' services: db: image: postgres:12.1-alpine environment: - TZ=Asia/Tokyo volumes: - ./tmp/db:/var/lib/postgresql/data web: build: . volumes: - .:/app ports: - 3000:3000 depends_on: - dbまず、サービスとして
dbとwebの二つがあることがわかるかと思います。dbは文字通りデータベース用のコンテナ(サービス)、webは Rails アプリケーションを動作させるコンテナ(サービス)です。dbコンテナではimageにpostgres:12.1-alpineを指定しています。
docker-compose.ymlについては前回もお話したので、前回お話していない項目を中心にお話します。
environment: コンテナを起動する時に環境変数としてセットする。この場合、TZ(タイムゾーン)を東京にしてる。volumes: コンテナからホストのディレクトリをマウントしている。左がホストのパス、右がコンテナ内のパス。ホストのパスはこのdocker-compose.ymlの場所からの相対パスで書いてます。こう書くことで簡単にいえば、ホストのパスとコンテナのパスを同期しているイメージになり、ホストでファイルを編集すればコンテナ内にも反映され、コンテナ内でファイルが編集されればホストのファイルにも反映されるという関係を気づけます。コンテナはステートレスなので一度コンテナを削除して新しくコンテナを起動させた場合、最初のコンテナ(削除したコンテナ)内で変更されたデータは全てなかったことになってしまうのですが、ホストのディレクトリに同期しておくことで次に起動するコンテナもそのディレクトリをマウントするのでデータが永続化されるようになります。build:build: .でdocker-compose.ymlと同じディレクトリのDockerfileをbuildしたイメージを使ってコンテナを起動するようになります。depends_on: コンテナの依存関係を定義します。今回の場合『webはdbに依存している』と定義していることになりますが、これは次の2つが実現されます。
docker-compose upした時に、dbコンテナが起動してからwebコンテナを起動するdocker-compose up webでwebコンテナを起動させようとした場合、dbコンテナも起動させるRails アプリケーションを新規作成
まずは
rails newコマンドで新規に Rails アプリを作成します。$ docker-compose run --rm --no-deps web rails new . -fGTd postgresql ... Webpacker successfully installed ??いろいろな要素のあるコマンドですね。ちょっと順を追って説明します。
まずこのコマンドの大枠はdocker-compose run [options] <service name> <command>です。今回の例では、
- [options]:
--rm --no-deps- <service name>:
web- <command>:
rails new . -fGTd postgresqlとなっています。
docker-compose runはdocker-compose.ymlの定義にそって対象のコンテナを立ち上げてその中でコマンドを実行し、実行後にコンテナを停止するコマンドです。つまり、webコンテナを立ち上げてrails new . -fGTd postgresqlをwebコンテナ内で実行してくれます。
--rmオプションはコマンド実行後にコンテナを停止した後に削除までしてくれるオプションです。基本停止したコンテナは不要だと思うのでこのオプションをつけるのがよきかと思います。
--no-depsオプションはdocker-compose.ymlでdepends_onが定義されていたとしてもそれを無視してdocker-compose runを実行することができます。次に
webコンテナで実行されるrails new . -fGTd postgresqlを見ていきましょう。
まずrails newは Rails アプリケーションを新規作成するためのコマンドです。.はアプリケーションを作成する場所を指していてカレントディレクトリ(コマンドが実行されたディレクトリ)を示しています。-fGTdはオプションなので一つずつ紐解きます。
-f: ファイルの上書きを強制する。Gemfileなどに上書きが走りますがいちいち Yes or No を聞かれないようにするためにつけています。-G: Gitの初期設定をスキップします。Rails 6 からなんかこのオプションをつけないとまともにrails newできなかったのでつけてます。-T:minitestという Rails でデフォルトでインストールされるテストフレームワークのインストールをスキップします。僕はRSpecというテストフレームワークをよく使っているのでこのオプションをつけて無駄にminitestがインストールされないようにしています。-d:-d <database name>で利用するデータベースを指定します。今回はpostgresqlを指定。Rails アプリケーションの新規作成ができたら一度イメージをビルドしておきましょう。
$ docker-compose build ... Successfully tagged handson_web:latest
docker-compose buildコマンドはdocker-compose.ymlでDockerfileからのビルドが必要なサービスのイメージビルドをすべて実行してくれます。今回はdbは DockerHub のイメージを使っているのでwebのみがビルドが必要なサービスとしてビルドされます。DBの接続設定
ビルドが終わったら、Rails アプリケーションの DB 接続設定をコーディングしていきます。 DB の接続設定は
config/database.ymlに記載します。 Rails では設定系のファイルはconfigディレクトリに格納されています。config/database.yml... default: &default adapter: postgresql encoding: unicode host: db username: postgres password: pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> ...
host、username、passwordがデフォルトから新たに追加した項目です。
hostはDBのホスト名です。今 Rails アプリが稼働しているwebコンテナはdocker-compose.ymlが作る Docker ネットワークの中にいます。この中ではサービス名で名前解決してコンテナが相互に接続することができます。つまりhostとしてdbを設定することでdocker-compose.ymlでdbのサービス名で定義されたコンテナに接続できるようになるのです。
usernameとpasswordは何の値なのでしょうか?これはdbコンテナのイメージで指定したpostgresのデフォルト値です。passwordは同じホストからのアクセスであれば省略が可能になっています。postgresイメージのusernameとpasswordはそれぞれPOSTGRES_USERとPOSTGRES_PASSWORDの環境変数で定義することもできます。データベースの設定はここまでです。このデフォルトの設定値が開発環境(
development)、テスト環境(test)の設定値として反映されるようになっています。データベースを作成する
データベースの接続設定を定義したので、データベースを実際に作成していきます。
Rails ではデフォルトで本番環境(production)、開発環境(development)、テスト環境(test)の3つの環境(environment)が用意されています。特別に環境を指定しない場合、開発環境で挙動するようになっています。
データベースの作成はrails db:createコマンドを使いますが、このコマンドは開発環境とテスト環境用にデータベースを作成してくれます。本番環境用のデータベースを作成する場合は、RAILS_ENV=productionをオプションとしてつけます。
今回はまず開発環境向けにデータベースの作成を行いたいので、以下のコマンドを実行します。$ docker-compose run --rm rails db:createHello Ruby on Rails on Docker!!
ここまでで Hello world に必要な作業は全て完了しました。
コンテナを立ち上げて Hello world ページが表示されることを確認しましょう。$ docker-compose up -dRails アプリは少し起動に時間がかかります。すぐに
http://localhost:3000にアクセスしてもまだアプリケーションが起動していないこともありますので、その場合はdocker-compose logsコマンドを使ってアプリケーションの起動状態を確認してみましょう。$ docker-compose logs -f
-fオプションはログの変化をリアルタイムでコンソールに表示するためのオプションです。Rails アプリが起動した場合web_1 | Use Ctrl+C to stopというログが表示されます。この表示を確認したら
Ctrl+Cでdocker-compose logsから抜け出しましょう。では、
http://localhost:3000にアクセスしてみましょう!
このようなページが表示されたでしょうか?このページが Rails アプリケーションの第一歩、つまり Hello world です。おめでとうございます!これでもう『Rails は Hello world までならやったことあります』と自慢することができます!ここまでできたら後片付けをしておきましょう。
このままではコンテナが起動しっぱなしになってしまうので、最後にコンテナを停止させておきます。$ docker-compose downこれでコンテナを停止させたので、
http://localhost:3000にアクセスしても先ほどのページは表示されなくなっていることでしょう。まとめ
今回は、
Dockerfileやdocker-compose.ymlなどのファイルを作成し、Rails アプリケーションを稼働させられる Docker イメージ、Docker コンテナを作成してみました。
さらに、Rails アプリを新規作成して Hello world に成功しました!
まだまだアプリケーション開発のほんの入り口ですが、Docker を使って Web アプリを起動させることができただけでもかなり感動があると思いますし、ここまでさほど大変ではないことも感じてもらえたかなと思います。これこそが Rails や Docker の偉大なところですね。次回は、
scaffoldという Rails の便利機能を使って、サンプル Web アプリケーションを作ってみようと思います。このscaffoldで作成できるアプリケーションが Rails の基本的なアプリケーションの形になりまして、その中には Rails アプリケーションを語る上では避けられないRESTfulやMVCの要素が詰まっていますので、その辺りも合わせて学んでいけるようにしようと思います。では、次回も乞うご期待!ここまでお読みいただきありがとうございました!
Reference
P.S. 間違っているところ、抜けているところ、説明の仕方を変えるとよりわかりやすくなるところなどありましたら、優しくアドバイスいただけると助かります。
- 投稿日:2020-02-04T12:04:56+09:00
コード書いたことないPdMやPOに捧ぐ、Ruby on Rails on Dockerハンズオン vol.2 -Hello, Ruby on Rails on Docker-
この記事はなにか?
この記事は私が社内のプログラミング未経験者、ビギナー向けに開催しているRuby on Rails on Dockerハンズオンの内容をまとめたものです。ていうかこの記事を基にそのままハンズオンします。ハンズオンは
1回の内容は喋りながらやると大体40~50分くらいになっています。お昼休みに有志でやっているからです。
現在進行形なので週1ペースで記事投稿していけるように頑張ります。
ビギナーの方のお役にたったり、同じように有志のハンズオンをしようとしている人の参考になれば幸いです。
他のハンズオンへのリンク
- Ruby on Rails on Dockerハンズオン vol.1 -Introduction-
$,#,>について
$: ローカルでコマンドを実行するときは、頭に$をつけています。
#: コンテナの中でコマンドを実行するときは、頭に#をつけています。
>: Rails console内でコマンド(Rubyプログラム)を実行するときは、頭に>をつけています。
はじめに
第二回目の今回は、Ruby on RailsをDockerコンテナで起動させるHello worldをやっていきます。
今日のゴール
- Ruby on Rails on Docker で Hello world する
では早速、Ruby on Rails on Docker で Hello world していきましょう!
Hello, Ruby on Rails on Docker
今回は↓の図のように、Docker 上に Rails アプリケーション用のコンテナと PostgreSQL (database) 用のコンテナを作っていきます。
まず、作業用のディレクトリを作っておきましょう。$ mkdir Handson $ cd Handson今後、この
Handsonディレクトリをホームディレクトリとして話を進めますので、特に指定がない場合、Handsonディレクトリでコマンドを叩いたり、Handsonディレクトリから見た相対パスでファイルを編集していると思ってください。では早速、Ruby on Rails on Docker な環境を構築するために以下の4つのファイルを作成していきます。
Dockerfile: Rails アプリ用の Docker image の元となる設計図Gemfile: Rails アプリに必要なgemを記載するファイルGemfile.lock:Gemfileによってインストールされたgemのバージョン情報などを管理するファイルdocker-compose.yml: 今回のアプリをコンテナ起動させるための Dcoker Compose ファイルDockerfile
DockerfileFROM ruby:2.7.0-alpine3.11 ENV HOME="/app" ENV LANG=C.UTF-8 ENV TZ=Asia/Tokyo WORKDIR $HOME RUN apk update && \ apk upgrade && \ apk add --no-cache \ gcc \ g++ \ libc-dev \ libxml2-dev \ linux-headers \ make \ nodejs \ postgresql \ postgresql-dev \ tzdata \ yarn && \ apk add --virtual build-packs --no-cache \ build-base \ curl-dev COPY Gemfile $HOME COPY Gemfile.lock $HOME RUN bundle install && \ apk del build-packs COPY . $HOME EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0"]Dockerfile は初めて見る人にとっては「なんだこれ?」なものな気がしますが、読んでみると意外とシンプルです。
頭に大文字で書かれているのが命令と呼ばれるものでコマンドみたいなものです。
今回の Dockerfile では以下の命令を利用しています。
FROM: ベースイメージを定義する命令です。ruby イメージを指定しているので、元々 Ruby を使用できるイメージの上に Rails を動かす環境を作っていきます。タグの2.7.0-alpine3.11は2020.02.02時点で Ruby の最新バージョンを軽量ディストリビューションとしておなじみの alpine linux のこれまた最新バージョン3.11上で動かしているものを選んでいます。ENV: 環境変数を定義する命令です。WORKDIR: 作業ディレクトリを定義する命令です。ベースイメージ内に該当のディレクトリがない場合は、そのディレクトリを作成することもしてくれます。COPY: ホストのファイルやディレクトリをイメージ内にコピーする命令です。RUN: コマンドを実行する命令です。EXPOSE: コンテナがリッスンするポートを宣言する命令です。 Rails ではデフォルトで 3000 番ポートを使用するので 3000 を指定してあげています。CMD: ソフトウェアを実行するためのコマンドを定義する命令です。コンテナが起動する時に実行されるコマンドといった方がイメージ湧きやすいかもしれません。少し特別な書き方(["xxx", "xxx"]みたいな)をしますが、Rails アプリケーションを起動させるコマンドはrails server -b 0.0.0.0でして、それをCMDの記法で書いています。あらかた命令と1行1行の内容について述べてしまいましたが、取りこぼしているところをキャッチアップ。
RUN宣言でapk ~と色々書いている9行目からの部分がありますが、apk addは Alpine linux でパッケージをインストールするコマンドです。
apk updateでパッケージリポジトリの最新のインデックス(インストールできる最新バージョンは何か)を取得してきて、apk upgradeですでにインストールしているパッケージで最新版にアップデートできるものをアップデートします。その後、apk addで Rails を起動するのに必要なパッケージをインストールしていきます。--no-cacheオプションはキャッシュを残さないようにするためのオプションです。不要なキャッシュを残さないことでコンテナ自体を軽量に保つことができます。(コンテナは軽量に保っておいた方がダウンロードに時間がかからなかったり、ホストのボリュームを圧迫しないのでよいとされています。)--virtualオプションはそのインストールしたパッケージ達を一つのグループとして名前づけしています。今回の例だとbuild-packsという名前をつけています。ここでインストールしたパッケージは Rails をビルドする上では必要なのですが起動させるためには不要なのであとでapk delで削除するために名前づけしています。その後、
COPY命令でGemfile、Gemfile.lockをイメージ内にコピーして、bundle installを実行してます。bundle installはGemfileの内容に沿ってgemをインストールするコマンドです。Rails 自体もgemでインストールできるのでGemfileにrailsを記入しておけばこのbundle installの際にインストールされます。Gemfile.lockはすでにインストール済のgemのバージョンなどを管理して無闇にバージョンアップさせないようにしてくれます。最後に
COPY . $HOMEでローカルホストのファイルを一式イメージ内にコピーすることで Rails アプリケーションを起動させられる Docker image を作ることができます。Gemfile
Gemfilesource 'https://rubygems.org' gem 'rails', '~>6'Gemfileはかなりシンプルで、インストールする
gemのソースとrailsgem をインストールすることを定義しています。Rails は2020.02.02時点で最新バージョンが 6.0.2 なのでまぁメジャーバージョンとして 6 のものをインストールしてくださいというような指定の仕方をしています。
Rails アプリケーションでは最初rails newコマンドでアプリに必要なgemやファイルをインストール・生成するため、初期ではこれほどシンプルなGemfileがあるだけで構わないのです。
Gemfileでバージョンを指定する表現方法はいくつかあります。gemはGitHubなどで公開されていることが多くて大体 README でこう Gemfile に記載してくれと書かれていることが多いのであんまり気にすることはないかもしれませんが一応紹介。
gem 'rails', '6.0.0': 絶対 6.0.0 をインストール(バージョンを定義)gem 'rails', >= 6.0.0': 6.0.0 より最新のものをインストール(最低バージョンを定義)gem 'rails', >= 6.0.0', < 6.0.2: 6.0.0 以上 6.0.2 未満のバージョンをインストール(バージョンの範囲を定義)gem 'rails', '~> 6.0.0': 6.0.X のバージョンをインストール(マイナーバージョンを定義)Gemfile.lock
Gemfile.lockは最初にbundle installされるときに書き込まれるので、最初は空ファイルで問題ありません。$ touch Gemfile.lock
touchコマンドはファイルの更新日時を現在時刻に更新するためのコマンドですが、ファイルが存在しない場合は空ファイルを生成してくれるのでGemfile.lockを生成するために使いました。docker-compose.yml
docker-compose.ymlversion: '3' services: db: image: postgres:12.1-alpine environment: - TZ=Asia/Tokyo volumes: - ./tmp/db:/var/lib/postgresql/data web: build: . volumes: - .:/app ports: - 3000:3000 depends_on: - dbまず、サービスとして
dbとwebの二つがあることがわかるかと思います。dbは文字通りデータベース用のコンテナ(サービス)、webは Rails アプリケーションを動作させるコンテナ(サービス)です。dbコンテナではimageにpostgres:12.1-alpineを指定しています。
docker-compose.ymlについては前回もお話したので、前回お話していない項目を中心にお話します。
environment: コンテナを起動する時に環境変数としてセットする。この場合、TZ(タイムゾーン)を東京にしてる。volumes: コンテナからホストのディレクトリをマウントしている。左がホストのパス、右がコンテナ内のパス。ホストのパスはこのdocker-compose.ymlの場所からの相対パスで書いてます。こう書くことで簡単にいえば、ホストのパスとコンテナのパスを同期しているイメージになり、ホストでファイルを編集すればコンテナ内にも反映され、コンテナ内でファイルが編集されればホストのファイルにも反映されるという関係を気づけます。コンテナはステートレスなので一度コンテナを削除して新しくコンテナを起動させた場合、最初のコンテナ(削除したコンテナ)内で変更されたデータは全てなかったことになってしまうのですが、ホストのディレクトリに同期しておくことで次に起動するコンテナもそのディレクトリをマウントするのでデータが永続化されるようになります。build:build: .でdocker-compose.ymlと同じディレクトリのDockerfileをbuildしたイメージを使ってコンテナを起動するようになります。depends_on: コンテナの依存関係を定義します。今回の場合『webはdbに依存している』と定義していることになりますが、これは次の2つが実現されます。
docker-compose upした時に、dbコンテナが起動してからwebコンテナを起動するdocker-compose up webでwebコンテナを起動させようとした場合、dbコンテナも起動させるRails アプリケーションを新規作成
まずは
rails newコマンドで新規に Rails アプリを作成します。$ docker-compose run --rm --no-deps web rails new . -fGTd postgresql ... Webpacker successfully installed ??いろいろな要素のあるコマンドですね。ちょっと順を追って説明します。
まずこのコマンドの大枠はdocker-compose run [options] <service name> <command>です。今回の例では、
- [options]:
--rm --no-deps- <service name>:
web- <command>:
rails new . -fGTd postgresqlとなっています。
docker-compose runはdocker-compose.ymlの定義にそって対象のコンテナを立ち上げてその中でコマンドを実行し、実行後にコンテナを停止するコマンドです。つまり、webコンテナを立ち上げてrails new . -fGTd postgresqlをwebコンテナ内で実行してくれます。
--rmオプションはコマンド実行後にコンテナを停止した後に削除までしてくれるオプションです。基本停止したコンテナは不要だと思うのでこのオプションをつけるのがよきかと思います。
--no-depsオプションはdocker-compose.ymlでdepends_onが定義されていたとしてもそれを無視してdocker-compose runを実行することができます。次に
webコンテナで実行されるrails new . -fGTd postgresqlを見ていきましょう。
まずrails newは Rails アプリケーションを新規作成するためのコマンドです。.はアプリケーションを作成する場所を指していてカレントディレクトリ(コマンドが実行されたディレクトリ)を示しています。-fGTdはオプションなので一つずつ紐解きます。
-f: ファイルの上書きを強制する。Gemfileなどに上書きが走りますがいちいち Yes or No を聞かれないようにするためにつけています。-G: Gitの初期設定をスキップします。Rails 6 からなんかこのオプションをつけないとまともにrails newできなかったのでつけてます。-T:minitestという Rails でデフォルトでインストールされるテストフレームワークのインストールをスキップします。僕はRSpecというテストフレームワークをよく使っているのでこのオプションをつけて無駄にminitestがインストールされないようにしています。-d:-d <database name>で利用するデータベースを指定します。今回はpostgresqlを指定。Rails アプリケーションの新規作成ができたら一度イメージをビルドしておきましょう。
$ docker-compose build ... Successfully tagged handson_web:latest
docker-compose buildコマンドはdocker-compose.ymlでDockerfileからのビルドが必要なサービスのイメージビルドをすべて実行してくれます。今回はdbは DockerHub のイメージを使っているのでwebのみがビルドが必要なサービスとしてビルドされます。DBの接続設定
ビルドが終わったら、Rails アプリケーションの DB 接続設定をコーディングしていきます。 DB の接続設定は
config/database.ymlに記載します。 Rails では設定系のファイルはconfigディレクトリに格納されています。config/database.yml... default: &default adapter: postgresql encoding: unicode host: db username: postgres password: pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> ...
host、username、passwordがデフォルトから新たに追加した項目です。
hostはDBのホスト名です。今 Rails アプリが稼働しているwebコンテナはdocker-compose.ymlが作る Docker ネットワークの中にいます。この中ではサービス名で名前解決してコンテナが相互に接続することができます。つまりhostとしてdbを設定することでdocker-compose.ymlでdbのサービス名で定義されたコンテナに接続できるようになるのです。
usernameとpasswordは何の値なのでしょうか?これはdbコンテナのイメージで指定したpostgresのデフォルト値です。passwordは同じホストからのアクセスであれば省略が可能になっています。postgresイメージのusernameとpasswordはそれぞれPOSTGRES_USERとPOSTGRES_PASSWORDの環境変数で定義することもできます。データベースの設定はここまでです。このデフォルトの設定値が開発環境(
development)、テスト環境(test)の設定値として反映されるようになっています。データベースを作成する
データベースの接続設定を定義したので、データベースを実際に作成していきます。
Rails ではデフォルトで本番環境(production)、開発環境(development)、テスト環境(test)の3つの環境(environment)が用意されています。特別に環境を指定しない場合、開発環境で挙動するようになっています。
データベースの作成はrails db:createコマンドを使いますが、このコマンドは開発環境とテスト環境用にデータベースを作成してくれます。本番環境用のデータベースを作成する場合は、RAILS_ENV=productionをオプションとしてつけます。
今回はまず開発環境向けにデータベースの作成を行いたいので、以下のコマンドを実行します。$ docker-compose run --rm rails db:createHello Ruby on Rails on Docker!!
ここまでで Hello world に必要な作業は全て完了しました。
コンテナを立ち上げて Hello world ページが表示されることを確認しましょう。$ docker-compose up -dRails アプリは少し起動に時間がかかります。すぐに
http://localhost:3000にアクセスしてもまだアプリケーションが起動していないこともありますので、その場合はdocker-compose logsコマンドを使ってアプリケーションの起動状態を確認してみましょう。$ docker-compose logs -f
-fオプションはログの変化をリアルタイムでコンソールに表示するためのオプションです。Rails アプリが起動した場合web_1 | Use Ctrl+C to stopというログが表示されます。この表示を確認したら
Ctrl+Cでdocker-compose logsから抜け出しましょう。では、
http://localhost:3000にアクセスしてみましょう!
このようなページが表示されたでしょうか?このページが Rails アプリケーションの第一歩、つまり Hello world です。おめでとうございます!これでもう『Rails は Hello world までならやったことあります』と自慢することができます!ここまでできたら後片付けをしておきましょう。
このままではコンテナが起動しっぱなしになってしまうので、最後にコンテナを停止させておきます。$ docker-compose downこれでコンテナを停止させたので、
http://localhost:3000にアクセスしても先ほどのページは表示されなくなっていることでしょう。まとめ
今回は、
Dockerfileやdocker-compose.ymlなどのファイルを作成し、Rails アプリケーションを稼働させられる Docker イメージ、Docker コンテナを作成してみました。
さらに、Rails アプリを新規作成して Hello world に成功しました!
まだまだアプリケーション開発のほんの入り口ですが、Docker を使って Web アプリを起動させることができただけでもかなり感動があると思いますし、ここまでさほど大変ではないことも感じてもらえたかなと思います。これこそが Rails や Docker の偉大なところですね。次回は、
scaffoldという Rails の便利機能を使って、サンプル Web アプリケーションを作ってみようと思います。このscaffoldで作成できるアプリケーションが Rails の基本的なアプリケーションの形になりまして、その中には Rails アプリケーションを語る上では避けられないRESTfulやMVCの要素が詰まっていますので、その辺りも合わせて学んでいけるようにしようと思います。では、次回も乞うご期待!ここまでお読みいただきありがとうございました!
Reference
P.S. 間違っているところ、抜けているところ、説明の仕方を変えるとよりわかりやすくなるところなどありましたら、優しくアドバイスいただけると助かります。
- 投稿日:2020-02-04T11:46:37+09:00
Centos8にDockerを入れてみる
本格的にCentos8を使い始めたので、いろいろ導入してみたことを記載します。
今回はDockerについてです。公式のインストール手順はこちらから。
ちなみに公式が公開している手順はCentos7ベースです。
私が試してみた際には2か所ほど引っ掛かりました。Docker インストール
古いパッケージの削除
新規インストールの場合は飛ばしてもよいかもしれません。
$ sudo dnf remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine 一致した引数がありません: docker 一致した引数がありません: docker-client 一致した引数がありません: docker-client-latest 一致した引数がありません: docker-common 一致した引数がありません: docker-latest 一致した引数がありません: docker-latest-logrotate 一致した引数がありません: docker-logrotate 一致した引数がありません: docker-engine 削除対象のパッケージはありません。 依存関係が解決しました。 行うべきことはありません。 完了しました!必要パッケージをインストールします。
$ sudo dnf install -y yum-utils \ device-mapper-persistent-data \ lvm2 CentOS-8 - AppStream 3.9 MB/s | 6.0 MB 00:01 CentOS-8 - Base 4.0 MB/s | 4.0 MB 00:01 CentOS-8 - Extras 2.5 kB/s | 2.1 kB 00:00 Extra Packages for Enterprise Linux Modular 8 - x86_64 24 kB/s | 21 kB 00:00 Extra Packages for Enterprise Linux 8 - x86_64 4.0 MB/s | 5.5 MB 00:01 Remi's Modular repository for Enterprise Linux 8 - x86_64 87 kB/s | 531 kB 00:06 Safe Remi's RPM repository for Enterprise Linux 8 - x86_64 142 kB/s | 1.4 MB 00:10 パッケージ yum-utils-4.0.8-3.el8.noarch は既にインストールされています。 パッケージ device-mapper-persistent-data-0.8.5-2.el8.x86_64 は既にインストールされています。 パッケージ lvm2-8:2.03.05-5.el8.0.1.x86_64 は既にインストールされています。 依存関係が解決しました。 行うべきことはありません。 完了しました!リポジトリを追加します。
$ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo Adding repo from: https://download.docker.com/linux/centos/docker-ce.repoDockerをインストールします。
そして引っ掛かりました。$ sudo dnf install docker-ce docker-ce-cli containerd.io CentOS-8 - AppStream 11 kB/s | 4.3 kB 00:00 CentOS-8 - Base 5.1 kB/s | 3.8 kB 00:00 CentOS-8 - Extras 3.7 kB/s | 1.5 kB 00:00 Docker CE Stable - x86_64 67 kB/s | 21 kB 00:00 Extra Packages for Enterprise Linux Modular 8 - x86_64 9.0 kB/s | 8.7 kB 00:00 Extra Packages for Enterprise Linux 8 - x86_64 14 kB/s | 9.3 kB 00:00 Remi's Modular repository for Enterprise Linux 8 - x86_64 3.2 kB/s | 3.5 kB 00:01 Safe Remi's RPM repository for Enterprise Linux 8 - x86_64 2.9 kB/s | 3.0 kB 00:01 エラー: 問題: package docker-ce-3:19.03.5-3.el7.x86_64 requires containerd.io >= 1.2.2-3, but none of the providers can be installed - cannot install the best candidate for the job - package containerd.io-1.2.10-3.2.el7.x86_64 is excluded - package containerd.io-1.2.2-3.3.el7.x86_64 is excluded - package containerd.io-1.2.2-3.el7.x86_64 is excluded - package containerd.io-1.2.4-3.1.el7.x86_64 is excluded - package containerd.io-1.2.5-3.1.el7.x86_64 is excluded - package containerd.io-1.2.6-3.3.el7.x86_64 is excluded (インストール不可のパッケージをスキップするには、'--skip-broken' を追加してみてください または、'--nobest' を追加し て、最適候補のパッケージのみを使用しないでください)どうやら
package containerd.ioで列挙されたバージョンが必要なのに、インストールができなかったようです。$ sudo dnf search --repo docker-ce-stable containerd.io ========================================== 名前 完全一致: containerd.io =========================================== containerd.io.x86_64 : An industry-standard container runtime検索してみるとパッケージはありました。
$ dnf info --repo docker-ce-stable containerd.io 利用可能なパッケージ 名前 : containerd.io バージョン : 1.2.10 リリース : 3.2.el7 Arch : x86_64 サイズ : 23 M ソース : containerd.io-1.2.10-3.2.el7.src.rpm リポジトリー : docker-ce-stable 概要 : An industry-standard container runtime URL : https://containerd.io ライセンス : ASL 2.0 説明 : containerd is an industry-standard container runtime with an emphasis on : simplicity, robustness and portability. It is available as a daemon for Linux : and Windows, which can manage the complete container lifecycle of its host : system: image transfer and storage, container execution and supervision, : low-level storage and network attachments, etc.infoで見てもバージョンに問題はなさそうなんですが。。。
$ sudo dnf --showduplicates search containerd.io ========================================== 名前 完全一致: containerd.io =========================================== containerd.io-1.2.0-1.2.beta.2.el7.x86_64 : An industry-standard container runtime containerd.io-1.2.0-2.0.rc.0.1.el7.x86_64 : An industry-standard container runtime containerd.io-1.2.0-2.2.rc.2.1.el7.x86_64 : An industry-standard container runtime containerd.io-1.2.0-3.el7.x86_64 : An industry-standard container runtimeインストール可能な全バージョンを検索してみたら、containerd.io-1.2.0 しかありませんでした。
infoで出たバージョンは何だったんだろう。。。?仕方がないので、ここから最新パッケージを落としてきてインストールします。
参考:CentOS8にDockerを入れるそしてまた引っ掛かりました。
$ wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.10-3.2.el7.x86_64.rpm $ sudo rpm -ivh containerd.io-1.2.10-3.2.el7.x86_64.rpm error: Failed dependencies: container-selinux >= 2:2.74 is needed by containerd.io-1.2.10-3.2.el7.x86_64container-selinux が必要ってことですね。
今のバージョンは。。。?$ sudo rpm -qa | grep container-selinux $oh...そもそもパッケージが入っていませんでした。
containerd.ioの二の舞にならないよう、念のため全バージョンを確認しておきましょう。
$ sudo dnf --showduplicates search container-selinux ======================================== 名前 完全一致: container-selinux ========================================= container-selinux-2:2.107-2.module_el8.1.0+237+63e26edc.noarch : SELinux policies for container runtimesバージョン問題はクリアしていますね。
インストールしましょう。$ sudo dnf install container-selinux 依存関係が解決しました。 =================================================================================================================== パッケージ Arch バージョン リポジトリー サイズ =================================================================================================================== インストール: container-selinux noarch 2:2.107-2.module_el8.1.0+237+63e26edc AppStream 44 k モジュールストリームの有効化: container-tools rhel8 トランザクションの概要 =================================================================================================================== インストール 1 パッケージ ダウンロードサイズの合計: 44 k インストール済みのサイズ: 40 k これでよろしいですか? [y/N]: y パッケージのダウンロード: container-selinux-2.107-2.module_el8.1.0+237+63e26edc.noarch.rpm 26 kB/s | 44 kB 00:01 ------------------------------------------------------------------------------------------------------------------- 合計 19 kB/s | 44 kB 00:02 トランザクションの確認を実行中 トランザクションの確認に成功しました。 トランザクションのテストを実行中 トランザクションのテストに成功しました。 トランザクションを実行中 準備 : 1/1 インストール中 : container-selinux-2:2.107-2.module_el8.1.0+237+63e26edc.noarch 1/1 scriptletの実行中: container-selinux-2:2.107-2.module_el8.1.0+237+63e26edc.noarch 1/1 検証 : container-selinux-2:2.107-2.module_el8.1.0+237+63e26edc.noarch 1/1 インストール済み: container-selinux-2:2.107-2.module_el8.1.0+237+63e26edc.noarch 完了しました!無事にインストールできました。
改めてcontainerd.ioをインストールします。$ sudo rpm -ivh containerd.io-1.2.10-3.2.el7.x86_64.rpm warning: containerd.io-1.2.10-3.2.el7.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY Verifying... ################################# [100%] Preparing... ################################# [100%] Updating / installing... 1:containerd.io-1.2.10-3.2.el7 ################################# [100%]こちらも無事にインストールできました。
ようやくDockerがインストールできます!
$ sudo dnf install docker-ce docker-ce-cli 依存関係が解決しました。 =================================================================================================================== パッケージ アーキテクチャー バージョン リポジトリー サイズ =================================================================================================================== インストール: docker-ce x86_64 3:19.03.5-3.el7 docker-ce-stable 24 M docker-ce-cli x86_64 1:19.03.5-3.el7 docker-ce-stable 39 M 依存関係のインストール: libcgroup x86_64 0.41-19.el8 BaseOS 70 k トランザクションの概要 =================================================================================================================== インストール 3 パッケージ ダウンロードサイズの合計: 64 M インストール済みのサイズ: 273 M これでよろしいですか? [y/N]: y パッケージのダウンロード: (1/3): libcgroup-0.41-19.el8.x86_64.rpm 54 kB/s | 70 kB 00:01 (2/3): docker-ce-19.03.5-3.el7.x86_64.rpm 11 MB/s | 24 MB 00:02 (3/3): docker-ce-cli-19.03.5-3.el7.x86_64.rpm 11 MB/s | 39 MB 00:03 ------------------------------------------------------------------------------------------------------------------- 合計 15 MB/s | 64 MB 00:04 warning: /var/cache/dnf/docker-ce-stable-091d8a9c23201250/packages/docker-ce-19.03.5-3.el7.x86_64.rpm: Header V4 RS A/SHA512 Signature, key ID 621e9f35: NOKEY Docker CE Stable - x86_64 13 kB/s | 1.6 kB 00:00 GPG 鍵 0x621E9F35 をインポート中: Userid : "Docker Release (CE rpm) <docker@docker.com>" Fingerprint: 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35 From : https://download.docker.com/linux/centos/gpg これでよろしいですか? [y/N]: y 鍵のインポートに成功しました トランザクションの確認を実行中 トランザクションの確認に成功しました。 トランザクションのテストを実行中 トランザクションのテストに成功しました。 トランザクションを実行中 準備 : 1/1 インストール中 : docker-ce-cli-1:19.03.5-3.el7.x86_64 1/3 scriptletの実行中: docker-ce-cli-1:19.03.5-3.el7.x86_64 1/3 scriptletの実行中: libcgroup-0.41-19.el8.x86_64 2/3 インストール中 : libcgroup-0.41-19.el8.x86_64 2/3 scriptletの実行中: libcgroup-0.41-19.el8.x86_64 2/3 インストール中 : docker-ce-3:19.03.5-3.el7.x86_64 3/3 scriptletの実行中: docker-ce-3:19.03.5-3.el7.x86_64 3/3 検証 : libcgroup-0.41-19.el8.x86_64 1/3 検証 : docker-ce-3:19.03.5-3.el7.x86_64 2/3 検証 : docker-ce-cli-1:19.03.5-3.el7.x86_64 3/3 インストール済み: docker-ce-3:19.03.5-3.el7.x86_64 docker-ce-cli-1:19.03.5-3.el7.x86_64 libcgroup-0.41-19.el8.x86_64 完了しました!さて、Dockerを起動してみましょう。
$ sudo systemctl start docker $ sudo systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled) Active: active (running) since Tue 2020-02-04 11:37:29 JST; 5s ago Docs: https://docs.docker.com Main PID: 14218 (dockerd) Tasks: 10 Memory: 44.6M CGroup: /system.slice/docker.service └─14218 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.169376623+09:00" level=info msg="ClientConn swi> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.194751667+09:00" level=warning msg="Your kernel> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.194778024+09:00" level=warning msg="Your kernel> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.194932968+09:00" level=info msg="Loading contai> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.410006453+09:00" level=info msg="Default bridge> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.504908668+09:00" level=info msg="Loading contai> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.522814914+09:00" level=info msg="Docker daemon"> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.523082762+09:00" level=info msg="Daemon has com> 2月 04 11:37:29 server1 dockerd[14218]: time="2020-02-04T11:37:29.550752482+09:00" level=info msg="API listen on > 2月 04 11:37:29 server1 systemd[1]: Started Docker Application Container Engine.問題なく動いているようです。
あとは自動起動の設定を忘れずに実施すれば完了ですね。$ sudo systemctl enable docker Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.お疲れ様でした。
- 投稿日:2020-02-04T10:59:18+09:00
Matlab 9.6 R2019a 稼働RuntimeのDockerイメージビルド
Matlab 9.6 R2019a は 2019年03月リリース
Dockerfile準備
Dockerfile.matlab.R2019a# Download and install Matlab Compiler Runtime v9.6 (2019a) # # This docker file will configure an environment into which the Matlab compiler # runtime will be installed and in which stand-alone matlab routines (such as # those created with Matlab's deploytool) can be executed. # # See http://www.mathworks.com/products/compiler/mcr/ for more info. FROM debian:10-slim ENV DEBIAN_FRONTEND noninteractive RUN apt-get -q update && \ apt-get install -q -y --no-install-recommends \ xorg \ unzip \ wget && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* # Install the MCR dependencies and some things we'll need and download the MCR # from Mathworks -silently install it RUN mkdir /mcr-install && \ mkdir /opt/mcr && \ cd /mcr-install && \ wget -q http://ssd.mathworks.com/supportfiles/downloads/R2019a/Release/5/deployment_files/installer/complete/glnxa64/MATLAB_Runtime_R2019a_Update_5_glnxa64.zip && \ unzip -q MATLAB_Runtime_R2019a_Update_5_glnxa64.zip && \ rm -f MATLAB_Runtime_R2019a_Update_5_glnxa64.zip && \ ./install -destinationFolder /opt/mcr -agreeToLicense yes -mode silent && \ cd / && \ rm -rf mcr-install # Configure environment variables for MCR ENV LD_LIBRARY_PATH /opt/mcr/v96/runtime/glnxa64:/opt/mcr/v96/bin/glnxa64:/opt/mcr/v96/sys/os/glnxa64:/opt/mcr/v96/sys/opengl/lib/glnxa64 ENV XAPPLRESDIR /opt/mcr/v96/X11/app-defaultsMatlab runtimeパス /opt/mcr/v96
Dockerfileイメージビルド
# タグ指定でイメージビルド docker build -t matlab-r2019a:latest -f Dockerfile.matlab.R2019a .
ご覧して頂き、どうも有難う御座います!
DevSamurai Ben
- 投稿日:2020-02-04T01:21:10+09:00
Dockerのコンテナ内でmigrateを実行すると「 failed: Name or service not known」と言われる件に関して
DockerでLaravelの環境構築をしてコンテナないで、php artisan migrateを実行すると下記のエラーが発生したので、解決策を忘備録として残しておきます。
エラー内容
root@a65fb3be52e4:/var/www# php artisan migrate Illuminate\Database\QueryException : SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known (SQL: select * from information_schema.tables where table_schema = todos_app and table_name = migrations and table_type = 'BASE TABLE') at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669 665| // If an exception occurs when attempting to run a query, we'll format the error 666| // message to include the bindings with SQL, which will make this exception a 667| // lot more helpful to the developer instead of just the database's errors. 668| catch (Exception $e) { > 669| throw new QueryException( 670| $query, $this->prepareBindings($bindings), $e 671| ); 672| } Exception trace: 1 PDOException::("PDO::__construct(): php_network_getaddresses: getaddrinfo failed: Name or service not known") /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 2 PDO::__construct("mysql:host=mysql;port=3306;dbname=todos_app", "root", "", []) /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 Please use the argument -v to see more details.
failed: Name or service not knownと言われているので設定ファイル内が怪しいということで確認してみることに。各種設定ファイル
.envDB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=todos_app DB_USERNAME=root DB_PASSWORD=rootdocker-composer.ymldb: image: mysql:5.7 container_name: db-host_2 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: todos_app MYSQL_USER: root MYSQL_PASSWORD: root TZ: 'Asia/Tokyo' command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ./docker/db/data:/var/lib/mysql - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf - ./docker/db/sql:/docker-entrypoint-initdb.d ports: - 3306:3306.envファイル内で設定している
DB_PORT,DB_DATABASE,DB_USERNAME,DB_PASSWORDはdocker-compose.ymlで設定しているものと同じなので問題はなさそう。。と思っていたのですが、こちらの記事によると、
DB_HOSTはIPアドレスではなくて、service名を指定するとのことでした。そのため.envファイルを下記に修正したら、無事にmigrateが実行されました。
.envDB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=todos_app DB_USERNAME=root DB_PASSWORD=root
- 投稿日:2020-02-04T01:21:10+09:00
Dockerのコンテナ内でmigrateを実行した際の「 failed: Name or service not known」に関して
DockerでLaravelの環境構築をしてコンテナないで、php artisan migrateを実行すると下記のエラーが発生したので、解決策を忘備録として残しておきます。
エラー内容
root@a65fb3be52e4:/var/www# php artisan migrate Illuminate\Database\QueryException : SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known (SQL: select * from information_schema.tables where table_schema = todos_app and table_name = migrations and table_type = 'BASE TABLE') at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669 665| // If an exception occurs when attempting to run a query, we'll format the error 666| // message to include the bindings with SQL, which will make this exception a 667| // lot more helpful to the developer instead of just the database's errors. 668| catch (Exception $e) { > 669| throw new QueryException( 670| $query, $this->prepareBindings($bindings), $e 671| ); 672| } Exception trace: 1 PDOException::("PDO::__construct(): php_network_getaddresses: getaddrinfo failed: Name or service not known") /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 2 PDO::__construct("mysql:host=mysql;port=3306;dbname=todos_app", "root", "", []) /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 Please use the argument -v to see more details.
failed: Name or service not knownと言われているので設定ファイル内が怪しいということで確認してみることに。各種設定ファイル
.envDB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=todos_app DB_USERNAME=root DB_PASSWORD=rootdocker-composer.ymldb: image: mysql:5.7 container_name: db-host_2 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: todos_app MYSQL_USER: root MYSQL_PASSWORD: root TZ: 'Asia/Tokyo' command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ./docker/db/data:/var/lib/mysql - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf - ./docker/db/sql:/docker-entrypoint-initdb.d ports: - 3306:3306.envファイル内で設定している
DB_PORT,DB_DATABASE,DB_USERNAME,DB_PASSWORDはdocker-compose.ymlで設定しているものと同じなので問題はなさそう。。と思っていたのですが、こちらの記事によると、
DB_HOSTはIPアドレスではなくて、service名を指定するとのことでした。そのため.envファイルを下記に修正したら、無事にmigrateが実行されました。
.envDB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=todos_app DB_USERNAME=root DB_PASSWORD=root






















