- 投稿日:2020-11-29T23:25:05+09:00
Dockerを使ってCakePHP2のブログチュートリアルの開発環境を構築しました。
1 はじめに
CakePHP2のアサインされたので、CakePHP2のブログチュートリアルをやりたいと思い、せっかくなのでDockerを使って環境構築することにしました。
OSはUbuntuで、Dockerのインストールが完了しているものとします。2 Dockerの考え方
この前Dockerの記事を書きましたのでそれも参考にしてください。
Dockerについて理解した後、実際に導入してみました。 - QiitaDockerでは、Dockerイメージというものを使ってコンテナを作成します。
このDockerイメージというものの手に入れ方は2つあります。
- 自分でDockerFileを作成して作る。
- 誰かがDockerFileを作成して作られたイメージをDockerHubから持ってくる。
- 既にあるコンテナをイメージ化する。(非推奨)
3のやり方は、どういうコンテナかわかりづらいのであまりよくないようです。
Docker Hubで公開されているDockerイメージも、それぞれDockerfileが公開されていて、それを元に作成されたイメージです。2.のやり方は、暫定的にDockerイメージにしておきたい場合などに行うくらいが良いと思います。
引用元:Docker入門(第三回)~各種dockerコマンドとDockerイメージ作成について~基本的には使用するDockerイメージのDockerFileは見れる状態にしておくのが良いみたいですね。
実際に、DockerHubに公開されているイメージのページにいくと、DockerFileが書かれていることが多いです。そして、DockerHubには様々なイメージが置いてあるので、もはや自分でDockerFileを書くのは面倒くさいです。
できればDockerHubからイメージを持ってきて楽したいですね。
そう思っていた時期が僕にもありました。・結局細かな設定は自分で行う。
・DockerHubで共有しようがDockerfileの内容を共有しようがあんまり手間が変わらない。等の理由で、結局自分でDockerfileを書くことのほうが多いという印象を、調べていく中で、うけました。
ちなみに、複数のコンテナを使うときはDockerComposeを使う必要があります。Docker Composeは、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。
引用元:Docker入門(第六回)〜Docker Compose〜 | さくらのナレッジブログチュートリアルでは、WebサーバとMySQLサーバの2つを使うので、DockerComposeを使う必要があります。
3 環境構築
それでは、環境構築をしていきます。
今回は、以下のサイトを参考に環境構築を進めていきます。
DockerでCakePHP2の開発環境を作ってみた(Mac版) – GeekGirl Cafe3.1 CakePHP2リポジトリのクローン
まず任意のディレクトリに作業ディレクトリを作成し、CakePHP2をクローンします。
$ mkdir blog-turorial $ git clone -b 2.x git://github.com/cakephp/cakephp.git blog-tutorialさて、クローンしたばかりのCakePHPリポジトリですが、これは全世界の人が使うバニラな状態です。
例えば我々は日本人なのでタイムゾーンを東京にしたり、アプリの名前とかを設定したりというのは、個別でしなければなりません。後程使用するMySQLコンテナとの接続設定なども必要です。まずは、以下のサイトを参考にそういう設定をしていきます。[CakePHP2]インストールの覚え書きです。 - Qiita
3.2 app/tmpのパーミッション修正
app/tmpのパーミッションを変える必要があります。
Apacheからのアクセスを可能にするためみたいです。
これについてはブログチュートリアル内でも説明があると思います。blog-tutorial$ sudo chmod -R 777 app/tmp3.3 タイムゾーン設定
タイムゾーンを設定する必要があります。東京にします。
blog-tutorial$ vi lib/Cake/Cache/CacheEngine.phpCacheEngine.phpif (!is_numeric($this->settings['duration'])) { date_default_timezone_set('Asia/Tokyo'); //追加 $this->settings['duration'] = strtotime($this->settings['duration']) - time(); }3.4 データベース設定
データベースの設定を行います。
普通はdatabase.phpはdatabase.php.defaultをコピーしてそれを参考に書きますが今回は新規作成でOKです。blog-tutorial$ vi app/Config/database.phpdatabase.phpclass DATABASE_CONFIG { public $default = array( 'datasource' => 'Database/Mysql', 'persistent' => false, 'host' => 'db', 'login' => 'root', 'password' => 'root_password', 'database' => 'blog_tutorial', 'prefix' => '', 'encoding' => 'utf8', ); }3.5 Security.saltの設定
Security.saltの設定をします。
これもブログチュートリアル内で説明がありますね。blog-tutorial$ vi app/Config/core.phpcore.php/** * A random string used in security hashing methods. */ Configure::write('Security.salt', 'pl345e-P45s_7h3*S@l7!'); //ランダムで長い文字列に変更 /** * A random numeric string (digits only) used to encrypt/decrypt strings. */ Configure::write('Security.cipherSeed', '7485712659625147843639846751'); //ランダムで長い数字列に変更3.6 DebugKitをインストール
DebugKitをインストールし、bootstrap.phpに読み込ませます。
blog-tutorial$ mkdir app/Config/Plugin/DebugKit blog-tutorial$ git clone https://github.com/cakephp/debug_kit -b 2.2 app/Config/Plugin/DebugKit blog-tutorial$ vi app/Config/bootstrap.phpbootstrap.php//コメントアウトを解除 CakePlugin::load('DebugKit');AppController.phpにも追加で記述します。
blog-tutorial$ vi app/Controller/AppController.phpAppController.phpclass AppController extends Controller { public $components = array('DebugKit.Toolbar'); //追加 }3.7 Dockerfileの作成
Dockerfileを作成します。
3.7.1 Dockerfile-apacheの作成
まずはApacheコンテナ用のDockerfileを作成します。
blog-tutorial$ mkdir docker blog-tutorial$ vi docker/Dockerfile-apacheDockerfile-apacheFROM php:5.6-apache RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ git \ zip \ unzip \ && rm -rf /var/lib/apt/lists # Enable PHP extensions RUN docker-php-ext-install pdo_mysql mysqli # Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer # Add cake and composer command to system path ENV PATH="${PATH}:/var/www/html/lib/Cake/Console" ENV PATH="${PATH}:/var/www/html/app/Vendor/bin" # COPY apache site.conf file COPY ./docker/apache/site.conf /etc/apache2/sites-available/000-default.conf # Copy the source code into /var/www/html/ inside the image COPY . . # Set default working directory WORKDIR ./app # Create tmp directory and make it writable by the web server RUN mkdir -p \ tmp/cache/models \ tmp/cache/persistent \ && chown -R :www-data \ tmp \ && chmod -R 770 \ tmp # Enable Apache modules and restart RUN a2enmod rewrite \ && service apache2 restart EXPOSE 803.7.2 Dockerfile-MySQLの作成
参考サイトではMySQLイメージは既存のものを使用していますが、それで作成したMySQLコンテナでは日本語が使えなかったので、こちらもDockerfileから作成していきます。
参考:DockerのMySQLコンテナを日本語対応させる - Qiita
blog-tutorial$ vi docker/Dockerfile-MySQLDockerfile-MySQLFROM mysql:5.7 RUN apt-get update RUN apt-get -y install locales-all ENV LANG ja_JP.UTF-8 ENV LANGUAGE ja_JP:ja ENV LC_ALL ja_JP.UTF-8 COPY ./docker/mysqld_charset.cnf /etc/mysql/conf.d/mysqld_charset.cnf3.8 Apache site.confの作成
dockerディレクトリにapahceディレクトリを作成し、site.confを作成します。
blog-tutorial$ mkdir docker/apache blog-tutorial$ vi docker/apache/site.confsite.conf<VirtualHost *:80> DocumentRoot /var/www/html/app/webroot/ <Directory /var/www/html/app/webroot/> Options FollowSymLinks AllowOverride All Require all granted </Directory> </VirtualHost>3.9 mysqld_charset.cnfの作成
dockerディレクトリにmysqld_charset.cnfを作成します。
blog-tutorial$ vi docker/mysqld_charset.cnfmysqld_charset.cnf[mysqld] character_set_server=utf8 character_set_filesystem=utf8 collation-server=utf8_general_ci init-connect='SET NAMES utf8' init_connect='SET collation_connection = utf8_general_ci' skip-character-set-client-handshake3.10 docker.compose.ymlの作成
docker.compose.ymlを作成します。
参考サイトではメールサーバーが立っていますが、ブログチュートリアルではいらないので、消します。blog-tutorial$ vi docker-compose.ymldocker-compose.ymlversion: "3" services: app: build: context: . dockerfile: docker/Dockerfile-apache volumes: - .:/var/www/html ports: - 8000:80 environment: TZ: "Asia/Tokyo" depends_on: - db db: build: context: . dockerfile: docker/Dockerfile-MySQL volumes: - db-data:/var/lib/mysql ports: - "3306:3306" environment: MYSQL_DATABASE: blog_tutorial MYSQL_ROOT_PASSWORD: root_password TZ: "Asia/Tokyo" volumes: db-data: external: false3.11 ビルド&実行
設定が完了したので、Docker Composeのビルドと実行を行います。
blog-tutorial/docker$ docker-compose build以下のような警告がいくつか出ますが無視でOKです。
Step 11/12 : RUN a2enmod rewrite && service apache2 restart ---> Running in 38bfaf787e92 Enabling module rewrite. To activate the new configuration, you need to run: service apache2 restart Restarting Apache httpd web server: apache2AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message . Removing intermediate container 38bfaf787e92 ---> 342196dde2c3気になるならビルド前に以下のサイトを参考にDockerfileを修正してください。
ビルドが終わったら実行しましょう。
blog-tutorial/docker$ docker-compose uplocalhost:8000にアクセスします。
上のほうにエラーが表示されていなく、文を囲む四角形が全部緑色だったらOKです!
4 終わりに
まだなんとなくしか理解できていませんが、それでもDockerは便利だなあと思ったので、今後Dockerを使わずに環境構築をすることはないのかなと思いました。
Twitterのフォローもお願いします!
- 投稿日:2020-11-29T22:52:38+09:00
Rust,Wasmの環境をDockerで作る MacOS
この記事の目的
rustとwasmの環境をdockerを使用して作ります。
元々はMacOSのローカルで環境を作ろうとした際に、
cargo install cargo-generateがエラーになってしまったので、それならdockerでやろうと思い立ち調べてみたところ上手く出来なかったため、後続の方に役に立っていただければと思い記録しました。
dockerのインストール方法については省略いたします。
dockerイメージをプルする
こちらで紹介されているdockerイメージをpullします。
docker pull secondstate/ssvm-nodejs-starter:v2作業フォルダを作成し、移動します。
mkdir rust_wasm cd rust_wasmdockerを起動します。
docker run -e USER=$USER -p 3000:3000 --rm -it -v $(pwd):/app secondstate/ssvm-nodejs-starter:v2コンテナの中に入りました。
nodeとcargo(rust)が入っていることが確認できます。npm -v #npmのバージョンが表示される cargo -version #cargoのバージョンが表示されるwasm-packとcargo-generateをインストールする
#wasm-packをインストールする curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh #cargo-generateをインストールする #cargo install cargo-generateだとエラーになります cargo install cargo-generate --features vendored-openssl以上です。
テンプレートを取ってきて動作を確認してみてください。
cargo generate --git https://github.com/rustwasm/wasm-pack-template所感
自分でdockerファイルを書くことができれば、wasm-packとcargogenerateのインストール部分はコンテナ起動の際に完了してしまうのだと思っています。
もし、ご自身でそういったイメージを作られた方、ないしはイメージを見つけた方がおりましたらコメントで教えていただけると大変嬉しいです。参考にした記事
Getting started with Rust functions in Node.js
https://www.secondstate.io/articles/getting-started-with-rust-function/ゼロからRust+WasmをFirebaseでデプロイするまでを簡単に
https://qiita.com/namn1125/items/8ffa0f87fa03f59f3acc
- 投稿日:2020-11-29T21:39:00+09:00
Transformation Advisor Localをインストールした時の手順メモ
1. はじめに
「TomcatのJavaアプリ(VM環境)をTransformation Advisorを使ってモダナイズする 」という投稿で、利用する Transformation Advisor Localのインストールをこの投稿で記述します。
このツールの使用例については、上記ページも参照ください。
2. Transformation Advisor Localとは
まず、Transformation Advisorはオンプレミス環境で動作しているJavaのミドルウェア・アプリケーションを分析し、生成されたマイグレーションバンドルを使って、 OpenShift の Libertyコンテナ上にJavaアプリをデプロイすることができるJavaアプリケーションのモダナイズするための移行支援ツールです。 (IBMの製品です。)
そして、Transformation AdvisorはOpenShift上にインストールしますが、
今回インストールするTransformation Advisor Localは、Windows・Linux・MacOSと、ローカルPCでもインストールして、Transformation Advisorを利用することができるツールです。詳細はこちら:IBM Cloud Transformation Advisor
仕組みとしては、ローカルPCに、DockerとDocker Composeをインストールして、Transformation Advisorのコンテナイメージを起動して、Transformation Advisorを利用します。
ローカルPCにインストールすることができるで気軽に試すことができますが、ローカルPCの性能によっては、Dockerを動かす時点で、もっさりと遅いという事が起こるかもしれません。
3. Transformation Advisor Localのインストール
今回は、Transformation Advisor Localの90日評価版をLinux ( CentOS7 )の環境にインストールする手順を確認しました。
3.1 前提
- 導入環境:
- VMWare ESXi 6.7 の仮想マシン( スペックは適当に設定CPU4コア, メモリ8GB, HDD 32GB)
- OS: CentOS Linux release 7.8.2003 (Core)の Minimam Install
- インストール手順書: Installing IBM Cloud Transformation Advisor locally
3.2 手順
DockerとDocker Composeのインストール
- 作業環境: CentOS7.8
Dockerの導入手順 https://docs.docker.com/get-docker
に沿って下記の手順でDockerをインストールします。$ sudo yum install yum-utils # docker のyum リポジトリ追加 $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # Dockerのインストール $sudo yum install docker-ce docker-ce-cli containerd.io #Dockerの起動 $sudo systemctl start docker # Dockerの動作確認 $ sudo docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 0e03bdcc26d7: Pull complete Digest: sha256:e7c70bb24b462baa86c102610182e3efcb12a04854e8c582838d92970a09f323 Status: Downloaded newer image for hello-world:latestDocker Composeのインストール
- 作業環境: CentOS7.8
Docker Composeの導入手順 https://docs.docker.com/compose/install/
に沿って下記の手順でDockerをインストールします。#docker-composeコマンドのダウンロード&設置 $ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose #docker-composeコマンドに実行権限追加 $ sudo chmod +x /usr/local/bin/docker-compose $ ls -l /usr/local/bin/docker-compose -rwxr-xr-x. 1 root root 12218968 Nov 29 04:34 /usr/local/bin/docker-composeTransformation Advisor Localのダウンロード
- 作業環境: ローカルPC
以下のURLよりTransformation Advisor Localの90日評価版をダウンロードします。(IBMアカウントが必要になります。)
https://www.ibm.com/account/reg/signup?formid=urx-38642ダウンロードページにて、「Transformation Advisor Localのインストールスクリプト」をダウンロードします。
Transformation Advisor Local の CentOS7.8へのインストール
- 作業環境: CentOS7.8
事前にローカルPCから CentOS7.8の環境に、先ほどダウンロードしたTransformation Advisor Localのバイナリ「 transformationAdvisor.zip」をアップロードしてください。
そして、以下の手順でインストールします。
#必要なツールのインストール(unzipとnetstatを導入) $ yum install -y unzip net-tools # Transformation Advisor Localの解凍 $ unzip transformationAdvisor.zip $ ls launchTransformationAdvisor.sh LICENSE LICENSES scripts transformationAdvisor.zipインストールのために「 ./launchTransformationAdvisor.sh 」を実行します。
$ sudo ./launchTransformationAdvisor.sh [sudo] password for dai: Docker Compose not installed. Please install docker-compose and re-run the script. https://docs.docker.com/compose/install/しかし、docker-composeがインストールされていないとメッセージが表示されます。これは、sudoのsecure_pathに docker-composeのインストールされているパスが登録されていないために、発生する事象です。
下記の様にvisudoを実行して、secure_pathに「 /usr/local/bin 」を追加してください。
$ sudo visudo (変更前)88 Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin (変更後)88 Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin再度、「launchTransformationAdvisor.sh」を実行して、インストールプログラムを起動します。 ライセンス情報が表示され、最後に、同意するか同意しないかの選択を 同意する 1 の選択をします。
sudo ./launchTransformationAdvisor.sh LICENSE INFORMATION The Programs listed below are licensed under the following License Information terms and conditions in addition to the Program license terms previously agreed to by Client and IBM. If Client does not have previously agreed to license terms in effect for the Program, the International License Agreement for Evaluation of Programs (Z125-5543-05) applies. Program Name (Program Number): IBM Cloud Transformation Advisor local 2.3.0 (Evaluation) The following standard terms apply to Licensee's use of the Program. ' ----- 省略 ----- ' 1) I have read and agreed to the license agreements 2) Don't accept the license agreementsその後、下記のようなオペレーションメニューが表示されるので、「1) Install Transformation Advisor」の 1 を入力してEnterを押してインストールを開始します。
Select the operation....... 1) Install Transformation Advisor 2) Uninstall Transformation Advisor (keep database data) 3) Uninstall Transformation Advisor (remove database data) 4) Stop Transformation Advisor 5) Start Transformation Advisor 6) Check for latest Transformation Advisor 7) Working in an Air Gapped Environment 8) Quitその後、正常にインストールが環境すると、下記の様にTransformation AdvisorのURLが表示されます。
Installing Transformation Advisor.............. Pulling db ... done Pulling server ... done Pulling ui ... done Creating network "scripts_default" with the default driver Creating scripts_db_1 ... done Creating scripts_server_1 ... done Creating scripts_ui_1 ... done Configuring Transformation Advisor............................................... Status ------------------------------------------------------------------------------------------------------ Transformation Advisor 2.3.0 is available for us at the following URL> http://192.168.26.253:3000Transformation Advisor への接続
- 作業環境: ローカルPC
ローカルPCのブラウザにて、前手順のインストール完了時に出力されるURLに接続し、Transformation Advisorの画面が表示されることを確認します。
4. 最後に
これで Transformation Advisor を利用することができるようになりました。
今回は、 Linux環境の手順を説明しましたが、Windows・MacOSの環境でも Docker・Docker Composeが導入済みの環境ならばインストールすることができます。Transformation Advisor の具体的な使用例は、「TomcatのJavaアプリ(VM環境)をTransformation Advisorを使ってモダナイズする 」の投稿をぜひ、ご覧ください。
- 投稿日:2020-11-29T21:31:26+09:00
【開発環境にDocker】Capistrano導入方法
今回はcapistranoでの自動デプロイの導入方法を備忘録のためまとめていきたいと思います。前回の記事からの続きとなります。
前提
手動でのデプロイができていることが前提の記事となります。また、細かい設定やインストールしているパッケージなどは下記事に手動でのデプロイ方法としてまとめてあるので、そちらからご確認いただけます。
https://qiita.com/shun0211/items/21871c82d385648b4bae環境
- Amazon Linux2 (無料枠)
- RDS (MySQL8.0)
- capistrano 3.14.1
- Ruby 2.7.1
- Rails 6.0.3.4
- Unicorn 5.7.0
- Nginx 1.12.2
Gemのインストール
gemfilegroup :development, :test do gem 'capistrano' gem 'capistrano-rbenv' gem 'capistrano-bundler' gem 'capistrano-rails' gem 'capistrano3-unicorn' endterminal$ bundle install $ bundle exec cap installこれにて、自動デプロイのための設定ファイルが作成されます
live_share ├ Capfile ├─ config │ ├─ deploy │ │ ├─production.rb #自動デプロイ時の本番環境での設定 │ │ └─staging.rb │ └─deploy.rb #自動デプロイ時の共通設定 └─ lib └─capistrano └─tasksCapistranoで自動デプロイをすると、サーバー上のディレクトリ構造は以下のようになります。(今回の設定の場合)
/var/www/rails(サーバー環境)live_share ├─ current # 最新のデプロイしたフォルダやファイルが置かれる ├─ shared # 共通のファイルが置かれる │ ├─ bundle │ ├─ config │ ├─ log │ ├─ public │ ├─ temp │ └─ vendor └─ release # 過去にデプロイしたフォルダやファイルが置かれる見て分かるように、階層構造が一段深くなっているので、NginxやUnicornの設定ファイルも修正する必要があります。
各ファイルの編集
まずは、Capfile, config/deploy.rb, config/deploy/production.rbのファイルを編集します。
capfilerequire "capistrano/setup" require "capistrano/deploy" require "capistrano/scm/git" install_plugin Capistrano::SCM::Git require "capistrano/rbenv" require "capistrano/bundler" require "capistrano/rails/assets" require "capistrano/rails/migrations" require 'capistrano3/unicorn' Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }config/deploy.rb# caipstranoのバージョンを記載します。バージョンはGemfile.lockに書いてあります。 lock "~> 3.14.1" set :application, "conefan" # pullしてくるgitのURLを書きます。 set :repo_url, "git@github.com:shun0211/live_share.git" # デフォルトのブランチはmasterになっているので、mainに変更します。 set :branch, "main" # デプロイするディレクトリを指定します。 set :deploy_to, "/var/www/rails/live_share" # capistranoではデプロイ後にバグが起きた場合、デプロイ前の状態に戻れるようにデプロイ前のファイルをrelesaseフォルダに入れます。その際、いくつ前のバージョンまで残しておくのかをここで設定します。 set :keep_releases, 2 # ssh接続をする際に必要な設定を書きます。 set :ssh_options, { # capistranoコマンド実行者の秘密鍵 port: 22, keys: %w(~/.ssh/live_share_key_rsa), forward_agent: true, auth_methods: %w(publickey) } # Railsがproduction.keyを参照するためのシンボリックリンクを貼る記述をします。production.keyについては後述 append :linked_files, 'config/credentials/production.key' # 同じくシンボリックリンクを貼るフォルダを指定します。記載したフォルダがshared下に作られます。 set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads') set :rbenv_type, :user set :rbenv_ruby, '2.7.1' set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" } set :unicorn_config_path, -> { "#{current_path}/config/unicorn.conf.rb" } after 'deploy:publishing', 'deploy:restart' namespace :deploy do task :restart do invoke 'unicorn:restart' end endconfig/deploy/production.rbserver "18.178.91.188", user: "ec2-user", roles: %w{web app db}また、前述したようにディレクトリ構造の変更により、NginxやUnicornの設定ファイルを変更する必要があるので、編集します。前回の記事ではUnicornの設定ファイルはサーバー上にしか書いていないので、サーバーにログインしてファイルの中身をローカルに持ってきて編集します。(たくさん試行錯誤をしていたので、前回の記事と書き方が異なっています)
Unicorn設定ファイル
config/unicorn.conf.rb(ローカル)#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく app_path = File.expand_path('../../../', __FILE__) worker_processes 2 working_directory "#{app_path}/current" #currentにします stderr_path "#{app_path}/shared/log/unicorn.stderr.log" #sharedにします stdout_path "#{app_path}/shared/log/unicorn.stdout.log" #sharedにします timeout 30 listen "#{app_path}/shared/tmp/sockets/.unicorn.sock" #sharedにします .unicorn.sockの.(ドット)を忘れずに pid "#{app_path}/shared/tmp/pids/unicorn.pid" #sharedにします preload_app true GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true check_client_connection false run_once = true before_exec do |server| ENV['BUNDLE_GEMFILE'] = "#{app_path}/current/Gemfile" #currentにします end before_fork do |server, worker| defined?(ActiveRecord::Base) && ActiveRecord::Base.connection.disconnect! if run_once run_once = false end # 古いプロセスがあった場合はkillする処理 old_pid = "#{server.config[:pid]}.oldbin" if File.exist?(old_pid) && server.pid != old_pid begin sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU Process.kill(sig, File.read(old_pid).to_i) rescue Errno::ENOENT, Errno::ESRCH => e logger.error e end end end after_fork do |_server, _worker| defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection endNginx設定ファイル
/etc/nginx/conf.d/live_share.conf(サーバー環境)error_log /var/www/rails/live_share/shared/log/nginx.error.log; #sharedにします access_log /var/www/rails/live_share/shared/log/nginx.access.log; #sharedにします upstream unicorn_server { server unix:/var/www/rails/live_share/shared/tmp/sockets/.unicorn.sock fail_timeout=0; #sharedにします } server { listen 80; client_max_body_size 4G; server_name conefan.com; #サーバー名 keepalive_timeout 5; root /var/www/rails/live_share/current/public; #currentにします location ~ ^/assets/ { root /var/www/rails/live_share/current/public; #currentにします } location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; if (!-f $request_filename) { proxy_pass http://unicorn_server; break; } } error_page 500 502 503 504 /500.html; }設定ファイルを再読み込みし再起動します。
/(サーバー環境)$ sudo service nginx reload $ sudo service nginx restart秘密鍵をDockerコンテナ上に配置
筆者は開発環境にDockerを使っていたので、Dockerコンテナ内の~/.sshディレクトリ内にEC2にログインするための秘密鍵を置かなければいけません。
live_share(ローカル)$ docker container cp ~/.ssh/<秘密鍵名> <コンテナ名>:/root/.sshこれでコンテナ内に秘密鍵が設置できたので、実際に入ってコンテナ内からEC2へログインできるか確認します。
live_share(ローカル)$ docker exec -it <コンテナ名> bash # コンテナ内で以下コマンド $ ssh -i ~/.ssh/<秘密鍵> ec2-user@18.178.91.188今後、ビルドし直す度に秘密鍵をコピーするのがめんどくさいため、volume化して~/.sshディレクトリを共有します。(.ssh内に他の秘密鍵がある場合はディレクトリを一段深くしてそこをvolume化したほうがいいかもしれません。)
docker-compose.ymlweb: # 省略 volumes: - ~/.ssh:/root/.ssh # 省略環境変数の設定
また、database.yml内で環境変数を使っているので、サーバー内でも設定しないといけません。前回の記事ではdotenvのGemを使っていたのですが、自動デプロイのときにはうまくいかなかったので、サーバー内の環境変数を設定します。(gotenvは本番環境では非推奨らしいです。)
/etc/environmemtDB_NAME=データベース名_production #RDSで作成したDB名 DB_USERNAME=root #RDSのユーザー名 DB_PASSWORD=********* #RDSのパスワード DB_HOSTNAME=***.ap-northeast-1.rds.amazonaws.com # RDSのエンドポイント環境変数が設定されているか確認
terminal$ source .env $ echo $DB_NAME $ echo $DB_USERNAME $ echo $DB_PASSWORD $ echo $DB_HOSTNAME環境変数の設定はcredentials.yml.encを使ってやる方法もあるみたいです。
production環境用にCredentialsの設定
手動デプロイとは異なり、production環境用のcredentialsの設定が必要になります。
live_share(ローカル)$ docker-compose run -e EDITOR=vim web rails credentials:edit --environment productionこのコマンドを打つことによりconfig/credentialsディレクトリが作られ、その中にproduction.keyとproduction.yml.encが作られます。デフォルトではsecret_key_baseは生成されないので自分で設定を行います。下記コマンドでヘルプが見れます。
live_share$ bin/rails credentials:edit --helpその後、生成されたproduction.keyをデプロイ先のサーバにコピーします。コピー先はshared/config/credentialsディレクトリに行います。
live_share(ローカル)$ scp -i ~/.ssh/live_share_key_rsa production.key ec2-user@18.178.91.188:/var/www/rails/live_share/shared/config/credentialsここまで来たらmainブランチにローカルで編集した設定の変更をマージしてデプロイを走らせます。
live_sharedocker-compose run --rm web bundle exec cap production deploy最後までデプロイが走れば成功です。お疲れさまでした!
何度もエラーが出ると思いますが、一個ずつ解決していけば必ずできるのでとにかく諦めないことが重要だと感じました。
ここからは筆者がハマったエラーについてまとめます。エラーについて
ssh接続エラー
コンテナ内に鍵を設置してssh接続できており、設定もまちがってないのに下のようなエラーが出る場合は一旦コンテナをビルドし直したほうがいいかもしれません。筆者はビルドし直すことでエラーがでなくなりました。
エラーログNet::SSH::AuthenticationFailed: Authentication failed for ~~~
Gem::LoadError
下エラーが出る場合はエラーログにもありますが、ed25519とbcrypt_pbkdfのGemをインストールすることで解決しました。
エラーログGem::LoadError : "ed25519 is not part of the bundle. Add it to your Gemfile."
Node.jsバージョンエラー
node.jsのバージョンが古い場合にエラーとなります。しかし、筆者の場合サーバー上で確認してもnodeのバージョンは10.21.0でした。なぜ6.17.1が使われているのかはなぞでしたが、新しいバージョンを再度インストールすることで解決しました。
エラーログThe engine "node" is incompatible with this module. Expected version ">=8.16.0". Got "6.17.1"/(サーバー上)# npmでnをインストール $ sudo npm install n -g # 安定版の最新node.jsをインストール $ sudo n stable バージョン確認 $ node -v参考
https://qiita.com/gyu_outputs/items/c960c903e7bc6f684a44
https://qiita.com/tatama/items/aaa1300f55da5da2933a
https://loumo.jp/archives/24419
- 投稿日:2020-11-29T20:45:54+09:00
docker-composeで都合の良いPython3実行環境を作成する
概要
- Python3の都合の良い実行環境が欲しくなったのでdockerで作成しました。
- いつも使ってるOSがCentOS7だ(ubuntuではない。。)
- ENVを切るのがめんどくさい。
- 検証のたびにサーバを準備したくない。
- 検証が終わったら消したい。
事前準備
- 下記をインストールし実行できること。
- docker
- docker-compose
ディレクトリ構成
./---docker-compose.yml |--Dockerfile |--requirements.txt # pipインストール用 利用しなければ不要 |--.env # 環境変数用 利用しなければ不要 |--src # pyファイルを配置するディレクトリ |-- sample.py各種ファイルの配置
docker-compose.yml
docker-compose.ymlversion: '3' services: python3: restart: always build: . container_name: 'python3' working_dir: '/root/src' tty: true volumes: - ./src:/root/src env_file: - .env
Dockerfile
FROM python:3 USER root RUN apt-get update RUN apt-get -y install locales && \ localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 ENV LANG ja_JP.UTF-8 ENV LANGUAGE ja_JP:ja ENV LC_ALL ja_JP.UTF-8 ENV TZ JST-9 ENV TERM xterm RUN apt-get install -y vim less RUN pip install --upgrade pip RUN pip install --upgrade setuptools ADD requirements.txt /root/ RUN pip install -r /root/requirements.txt
requirements.txt
- pipインストールする必要があれば記載する
requirements.txtrequests
.env
- 環境変数を設定する必要があれば記載する
SAMPLE_USER ='root'
sample.py
sample.pyprint("hello world")実行
コンテナを起動
$ docker-compose up -dスクリプトの実行
- dockerホストになっているサーバからexecでpythonスクリプトを実行できる。
$ docker-compose exec python3 python3 sample.py hello worldrequirements.txtや.envを修正したとき
- 一度停止して再ビルド
$ docker-compose down $ docker-compose build $ docker-compose up -d
- 投稿日:2020-11-29T19:42:34+09:00
30代未経験からRails, AWS, Docker, CircleCIでポートフォリオを作成するまで
プログラミング未経験の31歳男がRuby on Rails, jQuery, AWS, Docker, CircleCIといった技術を使ってWebアプリを作りました。
この記事では、最初にアプリの紹介をした後に、
- どれくらいの時間かけて作ったのか
- なぜこれらの技術を使うことにしたのか
- 特に大変だったところ
- どのように学習したのか
といったことについて、お伝えできればと思います。
どんなアプリを作ったのか
減量アプリです。(筋トレしてる人が健康的に体脂肪を減らすためのアプリ)
「これなら自分でも続けられる」をコンセプトに「PFC MASTER」というアプリを開発しました。
アプリのURLはこちらです。
https://pfcmaster.work/
(レスポンシブ対応しておりスマホからも見られますが、グラフが崩れます)Githubはこちらです。
https://github.com/naota7118/pfc-masterなんでこのアプリを作ったのか
僕自身が「減量がなかなか続かなくて、まだ腹筋を割れたことがない」という悩みを抱えていました。
自分自身の悩みを解決するようなアプリを作りたいと思い、減量アプリを作ることにしました。「どうしたら減量を途中で挫折せずに続けられるようになるかな?」
今まで減量に挫折した原因を考えたところ、下記の2つが思い当たりました。
〈これまで減量が続かなかった原因〉
- 1日どれくらい食べれば体脂肪落とせるのかわからなくて、適当に食べてしまっていた。
- 減量が進んでいるのかどうか、進捗がわからなくてモチベーションが保てなかった。
このような原因に対してどうしたら減量を続けやすくなるか考えた結果、下記の2つを思いつきました。
- 「1日何キロカロリーまで食べていいのか」を自分の体重から自動で計算してくれて、食べるごとに確認できたらカロリーコントロールしやすくなるのではないか。
- 体重やカロリーの推移をグラフで見られるようにすれば、成果が出てるのがわかってモチベーションが保てるのではないか。
このように原因やそれを解決する策を考えて、グラフ機能をメインとした減量アプリを作ることにしました。
アプリの写真と説明
トップページ
使い方を細かく説明しなくても、パッと見て一目で使い方わかる外観を意識して作りました。
グラフ
体重とカロリーの推移がグラフという形で見られるようにしました。
自分の頑張りが目に見えることで「よし、いい感じだ。もっと頑張ろう」と思えるのではないかと考えたのです。
カレンダーと画像一覧
食べたものや筋トレをカレンダーや写真で記録して確認できるようにしました。
写真でカラダの変化を可視化することでそれもモチベーションにつながると考えました。
また、他の減量に成功した方がどんなものを食べて減量できたのか知って真似できるため、という目的もあります。
カロリーの自動計算
「1日○キロカロリー食べれば体脂肪を落とせる」という減量の目安となる"1日の摂取カロリー目をユーザーが体重と体脂肪率を入力したら自動で計算されるようにしました。
※ちなみに、摂取カロリーの計算式はバズーカ岡田先生の著書『除脂肪メソッド』を参考にしました。
自動計算機能によって、「今日あと何キロカロリーまで食べて大丈夫か」がわかるようにしました。
これで減量の成功率を高められると考えました。
使用技術
フロントエンド
HTML(Haml), CSS(Sass), jQuery, boostrap4サーバーサイド
Ruby 2.5.1, Rails 5.2.4.3インフラ
CircleCI, Nginx, MySQL, Docker/Docker-compose, AWS(VPC, EC2, RDS, IAM, Route53, S3)サーバーサイドはRuby on Rails、フロントエンドはSassとjQueryで実装しました。
開発環境にはDocker-composeを使用しました。CI/CDパイプラインに関しては、CircleCIによりmasterブランチにmergeしたら自動でRSpecのテストとRubocopのリファクタリングが実行されるように設定しました。
ER図
インフラ構成図
アプリを作るのにかかった期間
トータル6ヶ月です。
当初の予定では8月にはAWSにデプロイした時点で転職活動を始める予定でしたが、「DockerやCirlcleCIを導入するところまでやり切りたい」と思い、結局6ヶ月かかりました。半年間どのように進めてきたかは下記の通りです。
期間 やったこと 2020年4月 テーマを決めた。データベース設計。 2020年5〜7月 (スクールのチーム開発と並行する形で)
RailsのCRUD機能、いいね機能(非同期通信)、コメント機能(非同期通信)、フォロー機能。
Chart.jsを使ったグラフ機能、jQueryを使った自動計算機能。2020年8月 Unicorn, Nginxを使ってAWSにデプロイ。
Capistranoを使って自動デプロイ。2020年9月 Haml, Sassで各ページのマークアップ。
Boostrapを使ってレスポンシブ対応させる。
Dockerを使って開発環境を構築。2020年10月 CircleCIでRSpecの自動テスト、Rubocopの自動リファクタリングを通す。
Gitのエラー解決で誤ってGitリポジトリのファイルを消してしまい、その修復のためAWSへのデプロイをやり直す。2020年11月 TwitterAPIを使って投稿するとTwitterに自動投稿されるように設定(ローカル環境のみ)。
転職活動開始。現在PHPで2つ目のアプリを開発中。なぜ6ヶ月もかかってしまったのか
誰にも相談せず1人でエラーを解決することにこだわり過ぎて、エラー解決に時間をかけ過ぎたことがいちばんの原因です。
エンジニアになるためには、「エラーに直面した時に"すぐ質問せず自分で問題解決する力"が求められる」との考えから、できるだけ自分でエラーを解決することにこだわっていました。
今振り返ると、リミットを設けてある程度自分で考えたら、リミットがきた時点で質問すべきだったと思います。
実際の仕事では1人のエラー解決をずっと待ってもらえないからです。現在、「2020年中に完成させる」というリミットを決めて2つめのアプリを開発しています。
なぜRails, jQuery, Docker, CircleCIを使うことにしたのか?
RailsとjQueryを選んだ理由
最速で開発する方法として、これらの技術を選びました。なるべく早くアプリを完成させ、転職活動を開始し、1日も早くエンジニアとして働きたいと思ったためです。
(結果的に半年もかかったので説得力ありませんが...)なぜRubyとjQueryを使えば最速で開発できると思ったかというと、スクールで簡単なCRUD機能を持ったアプリを開発した経験があり、他の言語に比べて理解していた部分が大きく開発する「こうやって作っていくんだ」というイメージがしやすかったためです。
AWS, Docker, CircleCIを使うことにした理由
これらの技術を使用した理由は、wantedlyで求人情報を見たところ、多くの企業でこれらの技術を使用していたためです。
「多くの企業で使われている技術はどんな技術なのだろう」と興味を持ったのと、実務で使うことを見越して「早いうちから自分で使って慣れておきたい」と考えたためです。特に大変だったところ
特に挙げるとすると、下記の6点です。
詰まったエラーの解決法をQiita記事にアウトプットしていました。
- Chart.jsを用いたグラフ機能
体重とカロリーをどうやってグラフで表示させるかで苦労しました。ただ大変さを感じると同時に、自分でロジックを考えるのが楽しく、プログラミングを始めて以来いちばん面白さを瞬間でもありました。
- AWSへのデプロイ
Qiita記事:デプロイしたのにアプリがブラウザに表示されない原因はunicorn.rbの設定にあった
Qiita記事:Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'の解決法
Qiita記事:libmysqlclient.so.18: cannot open shared object file: No such file or directoryの解決法
- Capistranoでの自動デプロイ
Qiita記事:bundle exec cap production deployで生じた6つのエラーの解決法(bundle exec cap production deployで生じた6つのエラーの解決法)
- CirlcleCIのconfig.ymlの設定
Qiita記事:CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
- Gitの中身が大きすぎる問題の解決
誤ってGitオブジェクトの中身を削除してしまい、その修復に苦労しました。
Qiita記事:[エラー解決プロセス説明].gitディレクトリ階下の容量が大きすぎるので小さくしたいどのように学習したのか
技術 学習方法 HTML/CSS/Ruby/Rails/jQuery スクールのカリキュラム Boostrap4 Boostrap日本語リファレンス AWS AWS:ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得
(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまでDocker 米国AI開発者がゼロから教えるDocker講座 CircleCI 米国AI開発者がゼロから教えるDocker講座 Chart.js Chart.js日本語ドキュメント 今後の課題
- 2日連続投稿した時に「すごい!!」と表示されるようにする。
- プロフィール画像を登録できるようにする。(現状は女性ユーザーも外国人男性がプロフィール画像になってしまう。)
- 運動した日と運動しなかった日をカレンダーでわかるようにする。
企業の方へ
ここまでお読みいただきありがとうございました。
現在、webエンジニアになるため転職活動を行っております。
少しでも興味を持って頂けましたら、Twitterの@naota7118までDM頂ければ幸いです。
何卒よろしくお願いいたします。
- 投稿日:2020-11-29T19:42:34+09:00
30代未経験からRails, AWS, Docker, CircleCIを使って減量アプリを作りました
プログラミング未経験の31歳男がRuby on Rails, jQuery, AWS, Docker, CircleCIといった技術を使ってWebアプリを作りました。
この記事では、最初にアプリの紹介をした後に、
- どれくらいの時間かけて作ったのか
- なぜこれらの技術を使うことにしたのか
- 特に大変だったところ
- どのように学習したのか
といったことについて、お伝えできればと思います。
どんなアプリを作ったのか
減量アプリです。(筋トレしてる人が健康的に体脂肪を減らすためのアプリ)
「これなら自分でも続けられる」をコンセプトに「PFC MASTER」というアプリを開発しました。
アプリのURLはこちらです。
https://pfcmaster.work/
(レスポンシブ対応しておりスマホからも見られますが、グラフが崩れます)Githubはこちらです。
https://github.com/naota7118/pfc-masterなんでこのアプリを作ったのか
僕自身が「減量がなかなか続かなくて、まだ腹筋を割れたことがない」という悩みを抱えていました。
自分自身の悩みを解決するようなアプリを作りたいと思い、減量アプリを作ることにしました。「どうしたら減量を途中で挫折せずに続けられるようになるかな?」
今まで減量に挫折した原因を考えたところ、下記の2つが思い当たりました。
〈これまで減量が続かなかった原因〉
- 1日どれくらい食べれば体脂肪落とせるのかわからなくて、適当に食べてしまっていた。
- 減量が進んでいるのかどうか、進捗がわからなくてモチベーションが保てなかった。
このような原因に対してどうしたら減量を続けやすくなるか考えた結果、下記の2つを思いつきました。
- 「1日何キロカロリーまで食べていいのか」を自分の体重から自動で計算してくれて、食べるごとに確認できたらカロリーコントロールしやすくなるのではないか。
- 体重やカロリーの推移をグラフで見られるようにすれば、成果が出てるのがわかってモチベーションが保てるのではないか。
このように原因やそれを解決する策を考えて、グラフ機能をメインとした減量アプリを作ることにしました。
アプリの写真と説明
トップページ
使い方を細かく説明しなくても、パッと見て一目で使い方わかる外観を意識して作りました。
グラフ
体重とカロリーの推移がグラフという形で見られるようにしました。
自分の頑張りが目に見えることで「よし、いい感じだ。もっと頑張ろう」と思えるのではないかと考えたのです。
カレンダーと画像一覧
食べたものや筋トレをカレンダーや写真で記録して確認できるようにしました。
写真でカラダの変化を可視化することでそれもモチベーションにつながると考えました。
また、他の減量に成功した方がどんなものを食べて減量できたのか知って真似できるため、という目的もあります。
カロリーの自動計算
「1日○キロカロリー食べれば体脂肪を落とせる」という減量の目安となる"1日の摂取カロリー目をユーザーが体重と体脂肪率を入力したら自動で計算されるようにしました。
※ちなみに、摂取カロリーの計算式はバズーカ岡田先生の著書『除脂肪メソッド』を参考にしました。
自動計算機能によって、「今日あと何キロカロリーまで食べて大丈夫か」がわかるようにしました。
これで減量の成功率を高められると考えました。
使用技術
フロントエンド
HTML(Haml), CSS(Sass), jQuery, boostrap4サーバーサイド
Ruby 2.5.1, Rails 5.2.4.3インフラ
CircleCI, Nginx, MySQL, Docker/Docker-compose, AWS(VPC, EC2, RDS, IAM, Route53, S3)サーバーサイドはRuby on Rails、フロントエンドはSassとjQueryで実装しました。
開発環境にはDocker-composeを使用しました。CI/CDパイプラインに関しては、CircleCIによりmasterブランチにmergeしたら自動でRSpecのテストとRubocopのリファクタリングが実行されるように設定しました。
ER図
インフラ構成図
アプリを作るのにかかった期間
トータル6ヶ月です。
当初の予定では8月にはAWSにデプロイした時点で転職活動を始める予定でしたが、「DockerやCirlcleCIを導入するところまでやり切りたい」と思い、結局6ヶ月かかりました。半年間どのように進めてきたかは下記の通りです。
期間 やったこと 2020年4月 テーマを決めた。データベース設計。 2020年5〜7月 (スクールのチーム開発と並行する形で)
RailsのCRUD機能、いいね機能(非同期通信)、コメント機能(非同期通信)、フォロー機能。
Chart.jsを使ったグラフ機能、jQueryを使った自動計算機能。2020年8月 Unicorn, Nginxを使ってAWSにデプロイ。
Capistranoを使って自動デプロイ。2020年9月 Haml, Sassで各ページのマークアップ。
Boostrapを使ってレスポンシブ対応させる。
Dockerを使って開発環境を構築。2020年10月 CircleCIでRSpecの自動テスト、Rubocopの自動リファクタリングを通す。
Gitのエラー解決で誤ってGitリポジトリのファイルを消してしまい、その修復のためAWSへのデプロイをやり直す。2020年11月 TwitterAPIを使って投稿するとTwitterに自動投稿されるように設定(ローカル環境のみ)。
転職活動開始。現在PHPで2つ目のアプリを開発中。なぜ6ヶ月もかかってしまったのか
誰にも相談せず1人でエラーを解決することにこだわり過ぎて、エラー解決に時間をかけ過ぎたことがいちばんの原因です。
エンジニアになるためには、「エラーに直面した時に"すぐ質問せず自分で問題解決する力"が求められる」との考えから、できるだけ自分でエラーを解決することにこだわっていました。
今振り返ると、リミットを設けてある程度自分で考えたら、リミットがきた時点で質問すべきだったと思います。
実際の仕事では1人のエラー解決をずっと待ってもらえないからです。現在、「2020年中に完成させる」というリミットを決めて2つめのアプリを開発しています。
なぜRails, jQuery, Docker, CircleCIを使うことにしたのか?
RailsとjQueryを選んだ理由
最速で開発する方法として、これらの技術を選びました。なるべく早くアプリを完成させ、転職活動を開始し、1日も早くエンジニアとして働きたいと思ったためです。
(結果的に半年もかかったので説得力ありませんが...)なぜRubyとjQueryを使えば最速で開発できると思ったかというと、スクールで簡単なCRUD機能を持ったアプリを開発した経験があり、他の言語に比べて理解していた部分が大きく開発する「こうやって作っていくんだ」というイメージがしやすかったためです。
AWS, Docker, CircleCIを使うことにした理由
これらの技術を使用した理由は、wantedlyで求人情報を見たところ、多くの企業でこれらの技術を使用していたためです。
「多くの企業で使われている技術はどんな技術なのだろう」と興味を持ったのと、実務で使うことを見越して「早いうちから自分で使って慣れておきたい」と考えたためです。特に大変だったところ
特に挙げるとすると、下記の6点です。
詰まったエラーの解決法をQiita記事にアウトプットしていました。
- Chart.jsを用いたグラフ機能
体重とカロリーをどうやってグラフで表示させるかで苦労しました。ただ大変さを感じると同時に、自分でロジックを考えるのが楽しく、プログラミングを始めて以来いちばん面白さを瞬間でもありました。
- AWSへのデプロイ
Qiita記事:デプロイしたのにアプリがブラウザに表示されない原因はunicorn.rbの設定にあった
Qiita記事:Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'の解決法
Qiita記事:libmysqlclient.so.18: cannot open shared object file: No such file or directoryの解決法
- Capistranoでの自動デプロイ
Qiita記事:bundle exec cap production deployで生じた6つのエラーの解決法(bundle exec cap production deployで生じた6つのエラーの解決法)
- CirlcleCIのconfig.ymlの設定
Qiita記事:CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
- Gitの中身が大きすぎる問題の解決
誤ってGitオブジェクトの中身を削除してしまい、その修復に苦労しました。
Qiita記事:[エラー解決プロセス説明].gitディレクトリ階下の容量が大きすぎるので小さくしたいどのように学習したのか
技術 学習方法 HTML/CSS/Ruby/Rails/jQuery スクールのカリキュラム Boostrap4 Boostrap日本語リファレンス AWS AWS:ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得
(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまでDocker 米国AI開発者がゼロから教えるDocker講座 CircleCI 米国AI開発者がゼロから教えるDocker講座 Chart.js Chart.js日本語ドキュメント 今後の課題
- 2日連続投稿した時に「すごい!!」と表示されるようにする。
- プロフィール画像を登録できるようにする。(現状は女性ユーザーも外国人男性がプロフィール画像になってしまう。)
- 運動した日と運動しなかった日をカレンダーでわかるようにする。
ここまでお読みいただきありがとうございました。
現在、webエンジニアになるため転職活動を行っております。
もし企業の採用担当者の方で、この記事を読んで少しでも興味を持って頂くなんてことがもしありましたら、Twitterの@naota7118までDM頂ければ幸いです。
何卒よろしくお願いいたします。
- 投稿日:2020-11-29T19:16:13+09:00
【Node.js】 Dockerを用いてNode.js Express MySQLの環境を構築する
前回の記事で作ったdockerファイルを整理した内容です。
【Node.js】 Dockerを用いてNode.js Express MySQLの環境を構築するまでの道のり
https://qiita.com/sho_U/items/0ef3dfc7b07b5e13fa18最初に用意するパッケージ
app.env
app.envMYSQL_SERVER=mysql MYSQL_USER=(ユーザー名) MYSQL_PASSWORD=(パスワード) MYSQL_DATABASE=(データーベース名)docker-compose.yml:
node.jsコンテナとmysqlコンテナを管理するyml
docker-compose.ymlversion: '3' services: mysql: image: mysql:5.7 container_name: (アプリ名)_db env_file: ./mysql/mysql.env environment: - TZ=Asia/Tokyo ports: - '3306:3306' volumes: - ./mysql/conf:/etc/mysql/conf.d/:ro - mysqldata:/var/lib/mysql networks: - backend app: build: . container_name: (アプリ名)_app env_file: ./app.env environment: - TZ=Asia/Tokyo - DEBUG=app:* tty: true ports: - '3000:3000' volumes: - ./src:/app working_dir: /app command: npm starttre networks: - backend depends_on: - mysql #使用するネットワークを作成。docker-composeの場合service以下の名前を使って名前解決されるため、appとmysqlが自動的に接続される。 networks: backend: volumes: mysqldata:Dockerfile:
アプリケーション用(node.js)コンテナを作るためのfile
dockerfile.FROM node:12 WORKDIR /appなぜかnpm installをRUNできないので,必要なパッケージはpackage.jsonに記載して、コンテナからnpm install を実施。
my.conf:
(コンテナ側の/etc/mysql/conf.d/に配置される。)
mysql/conf/my.conf[client] default-character-set=utf8mb4 [mysql] default-character-set=utf8mb4 [mysqldump] default-character-set=utf8mb4 [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_bin lower_case_table_names=1 # Enable access from the host machine. bind-address=0.0.0.0mysql.env
mysql/mysql.envMYSQL_ROOT_HOST=% MYSQL_ROOT_PASSWORD=(ルートパスワード) MYSQL_USER=(ユーザー名) MYSQL_PASSWORD=(パスワード) MYSQL_DATABASE=(データーベース名)src:
アプリケーション本体(空ディレクトリ)
package.json:
初期は空
package.json(空){}アプリケーション用のコンテナを作成する
コンテナをビルドする。
ホスト.docker-compose buildホスト.#コンテナを一時的に起動(--rmで停止後削除する。コンテナ起動後、bashに入る) docker-compose run --rm app /bin/bashコンテナ.# express-generatorでアプリケーションのひな形を生成 npx express-generator --view=ejspackage.jsonに必要なパッケージを記載(必要に応じて追加)
package.json{ "name": "アプリ名", "version": "0.0.0", "private": true, "scripts": { "start": "nodemon ./bin/www" //nodemon用起動scripts }, "dependencies": { "cookie-parser": "~1.4.4", "debug": "~2.6.9", "ejs": "^3.1.5", "express": "~4.16.1", "express-generator": "^4.16.1", "express-session": "^1.17.1", "express-validator": "^6.7.0", "http-errors": "~1.6.3", "morgan": "~1.9.1", "nodemon": "^2.0.6", "sequelize": "^6.3.5", "sequelize-cli": "^6.2.0" } }コンテナ.#インストール npm installコンテナ.#コンテナを抜ける(この仮コンテナは削除される) exit※この時、コンテナは削除されるが
docker-compose.ymlvolumes: - ./src:/appこの記述により、.(docker-compose.ymlがあるディレクトリ。つまりnodoDockerディレクトリの配下のsrcディレクトリにマウントされているため、ホスト側のsrcディレクトリに作成した雛形は残っている。
コンテナを起動させる
host.docker-compose updocker-compose.ymlcommand: npm startの記載により、コンテナ起動後、自動的にExpress.jsのアプリケーションがnodemonで起動する。
http://localhost:3000/
で確認。mysqlコンテナに入れるか確認
docker exec -it コンテナID bash mysql -uroot -p
- 投稿日:2020-11-29T18:40:56+09:00
CircleCI で DLC を(一部) 使わなくなった話
Increments × cyma (Ateam Inc.) Advent Calendar 2020 の7日目は、
Increments株式会社 プロダクト開発グループ Qiita開発チームの @atm-snag が担当します!閑話
この記事を書いているときに,前日の記事がアップされていて,
それが CI 関連だったので, CI が連続するなあと思った(小並感はじめに
Increments では,build や deploy などに circleci を使っています.
circleci には DLC(Docker Layer Cache) という機能があります.
今回は,DLC を使わなくなった話をします.DLC とは…
- circleci の executer を跨いで
/var/lib/docker
を共有する仕組みです.
- docker のイメージレイヤをジョブをまたいで使うことができる
- ジョブ実行 1 回ごとに 200 [クレジット] かかる(200 credits per job run)
です.
circleci に詳しくない人に軽く説明すると,
- executor とは
- ジョブの実行環境.
- 通常 executer は別マシンで起動して不連続なので ,
/var/lib/docker
は共有されていない状態
docker build
するときに過去のイメージレイヤのキャッシュがない → build が長い → 金銭的な死DLC を使えば,どこかのジョブで
docker build
が終わっていれば,
次以降に起動する executor では,キャッシュを使って,docker build の実行をスキップ(USING CACHE) できるという訳です.
これは便利.→ ジョブなどの概念はこちらが詳しそう
問題点
使っているうちにいくつか気付いたことがあります.
Dockerfile
等のビルドの実行に関係ある部分に変更が無い場合でもキャッシュを使わずに build が実行されていることがあった
- おそらく,volume が複数あるために,docker イメージレイヤがキャッシュとして有効に使われていない状態だった
- ドキュメントに,1つのvolume にアタッチできるのが1つの executor なため,volume は複数個になる(最大50個) ことがあると書いてある
- volumen が消えるのが1週間後であり,どういう条件でどのvolume が使われるのかはランダム(?)
- circleci の課金1が,ジョブの実行時間とリンクしているので,できれば無駄な docker build は避けたい
- 結局安くなっているのか?
- docker のイメージレイヤがキャッシュされていても,build が必要なステップがあれば,そのステップはは実行される
- 速度的には,「キャッシュなし < DLC < 過去の image を pull してcache できるところはする」のような想定(下図)
- 「image pull」 と 「DLC」 の差はdocker イメージレイヤをpull する時間がメイン
docker build
が成功する確率が高い前提- 1回 200クレジットかかる.
- 例えば,machine executor medium で 10 [クレジット/分]1
200[クレジット] / 10[クレジット/分] → build 時間を20分以上高速化できないとコスト的には微妙ではないか?
もっと言うと,docker pull する時間が 20分を越えなければ DLC より docker pull の方が(コスト的には)良いのではないか?2
(時間的にはdocker pull
する分だけ悪くなるために一長一短ではある.あと volume が複数あることでbuild する可能性があること.もある)やったこと
- docker pull を build よりも前に実行するようにした
- docker-registory-image-cache みたいな
- docker pull しても 10分かかるようなことはない.
DLC も良いところもある
- 例えば,色んなジョブで DLC を使うことで,キャッシュヒット率を上げる
- docker pull を使うと,失敗した build の image layer の情報は残らないため,そのようなものを積極的に使おうとするならば有効かもしれない
- とはいえ,これはエッジケース寄りな感じがする.circleci のジョブで
docker build
をなるべく失敗させないように運用でカバーすることもできる.- 提案っぽいもの
- DLC ではなくジョブで使えるキャッシュ機能も存在してそちらはどのキャッシュをなるべく使う指定ができるので,どういうvolume を優先して使うかを指定できるとある程度使い易くなるのではないか?
- なんかこう,branchとか開発project みたいな感じで,そっちのvolume を優先的に使いたい.みたいなケース.
- 今回試した方法は docker pull に依存しているので,docker pull に何らかの制限をかけられるとローカルのキャッシュの方がありがたい
- 例えば,pull に回数制限かけられたりした場合
その他
- 試してみたプロジェクトでは,docker save → store cache → restore cache → docker load がめちゃ時間かかったので,docker pull を採用しました
- 近いところでやるから速くなると思ったんだけど,やっぱり計測してみないとわからないもんですね.
まとめ
- DLC を使わなくなりました(一部)
- 今回のプロジェクトではマッチしなかったので使わなくなったけど,有意に使える場面もあるかもしれない.
- とはいえ,中身を知らないといつ使えるんだということになるので,今回のように調べることができたのは良かった.
Increments × cyma (Ateam Inc.) Advent Calendar 2020 の8日目は、エイチームのEC事業本部の @hibiheion がお送りします!!
LINK
転送量課金とかできたら,
docker pull
の方が不利になることも起きるだろうか? ↩
- 投稿日:2020-11-29T17:12:48+09:00
docker-composeを使った開発環境構築実践! Rails + Nuxt.js + MySQLを動かす
はじめに
docker-composeを使ったローカル開発環境構築について解説します!
ここでは、フロントエンドにNuxt.js, バックエンドにRails, DBにMySQLを使った構成にします。
YouTube動画
動画で確認したい方はこちらもどうぞ!
【YouTube動画】 docker-compose による開発環境構築入門
GitHub
GitHubにコードを載せているので、実際に動かしてみたい方はこちらもどうぞ!
https://github.com/yassun-youtube/docker-compose-samplegit clone git@github.com:yassun-youtube/docker-compose-sample.git
実際のコード
docker-compose.ymlversion: "3.8" services: rails: build: ./rails-sample ports: - 3000:3000 volumes: - ./rails-sample:/app - /app/node_modules stdin_open: true tty: true command: sh -c "yarn && bundle exec rails server -b 0.0.0.0 -p 3000" depends_on: - mysql nuxt: build: ./nuxt-sample ports: - 8000:8000 volumes: - ./nuxt-sample:/app - /app/node_modules command: sh -c "yarn && yarn dev" mysql: image: mysql:8.0.22 volumes: - db-data:/var/lib/mysql environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: test-database volumes: db-data:# ./nuxt-sample/Dockerfile FROM node:14.15.1-alpine3.12 WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install CMD ["yarn", "dev"]# ./rails-sample/Dockerfile FROM ruby:2.7.1-alpine RUN set -x && apk add --no-cache \ # for mysql mysql-dev \ # for nokogiri build-base \ # for tzinfo-data tzdata \ yarn WORKDIR /app COPY Gemfile Gemfile.lock package.json yarn.lock ./ RUN bundle install RUN yarn install CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0"]database.ymldefault: &default adapter: mysql2 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default username: root password: database: rails-sample-dev host: mysql test: <<: *default username: root password: database: rails-sample-test host: mysqlnuxt.config.js... proxy: { '/api': 'http://rails:3000' }, ...
docker-composeとは
docker-composeとは複数コンテナやネットワーク、ボリュームを一括管理できるツールです。
Dockerをインストールすれば、ついてくるので、別途インストールする必要はありません。よく使うコマンド
docker-composeでよく使うコマンドを紹介します。
docker-compose up
docker-compose.ymlに記載されたコンテナを起動するために使います。
-d
オプションを付けると、デタッチモードで起動します。docker-compose down
起動したコンテナを停止して削除するときに使います。
削除しない場合は、CTRL + Cを押すかdocker-compose stop
で止めることができます。コンテナをデタッチモードで動かしているときは、
docker-compose ps
と併用して使います。docker-compose build
docker-compose.ymlに記載されたサービス (nuxtとかrails, mysql) をビルドするときに使います。
ymlファイル内のimage:
またはbuildに書かれているパスにあるDockerfileのイメージを参照して、ビルドを開始します。docker-compose run <サービス名> <コマンド>
docker-compose.ymlに記載されたサービスを指定してコマンドを実行するときに使います。
docker-compose exec <サービス名> <コマンド>
既に起動しているコンテナを指定して、コマンドを実行するときに使います。
docker-compose.ymlの概要
docker-compose.ymlで指定できる、
version
services
networks
volumes
について紹介します。version
docker-composeの書き方のバージョンを指定するときに使います。
この記事を書いている段階 (2020/11/29) では、3.8です。services
コンテナを定義するために使います。
ここで、railsとかnuxt, mysqlのDockerfileを指定したり、イメージを直接指定して使います。networks
各サービスがどのネットワークと接続するかを定義できます。
volumes
ホストOSとゲストOSでデータを同期するときに使います。
今回はMySQLのデータを同期するために使います。実際の設定ファイル
実際の設定ファイルは以下のようになります。
docker-compose.ymlversion: "3.8" services: rails: build: ./rails-sample ports: - 3000:3000 volumes: - ./rails-sample:/app - /app/node_modules stdin_open: true tty: true command: sh -c "yarn && bundle exec rails server -b 0.0.0.0 -p 3000" depends_on: - mysql nuxt: build: ./nuxt-sample ports: - 8000:8000 volumes: - ./nuxt-sample:/app - /app/node_modules command: sh -c "yarn && yarn dev" mysql: image: mysql:8.0.22 volumes: - db-data:/var/lib/mysql environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: test-database volumes: db-data:大枠の設定
上記設定ファイルの大枠をみていきます。
設定ファイルはバージョン3.8を利用し、サービスにはrails, nuxt, mysqlを指定しています。
DBのデータを同期するために、volumes: db-data:
を指定しています。docker-compose.ymlversion: "3.8" services: rails: ... nuxt: ... mysql: ... volumes: db-data:services: mysqlの設定
imageでMySQL 8.0.22のDockerイメージを取得し、volumesでデータを同期しています。
environmentで環境変数を設定でき、ここではrailsからROOTユーザーとして、アクセスできるようにしています。
また、作成するDB名はtest-databaseとしました。docker-compose.ymlmysql: image: mysql:8.0.22 volumes: - db-data:/var/lib/mysql environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: test-databaseservices: nuxtの設定
nuxtは別途Dockerfileを作成し、そこからイメージを取るようにしました。
Dockerfileの場所をbuildで指定しています。portsでは、ホストOSの8000ポートとゲストOSの8000ポートを繋げる設定をしています。
volumesの1行目
./nuxt-sample:/app
は、ホストOSのnuxt-sampleをゲストOSのappと同期するための設定です。
2行目の/app/node_modules
はホストOSのnode_moduleとゲストOSのnode_moduleを同期しないための設定です。
node_modulesはOS依存のパッケージが入る可能性があるので、このように除外しています。commandでは、コンテナ起動時にシェルで実行するコマンドを設定しています。
node_modulesを作るために、yarn
を実行し、yarn dev
でnuxtを起動しています。docker-compose.ymlnuxt: build: ./nuxt-sample ports: - 8000:8000 volumes: - ./nuxt-sample:/app - /app/node_modules command: sh -c "yarn && yarn dev"次にDockerfileをみていきます。
FROMで使用するDockerイメージを指定します。
開発環境なので、軽量なalpineにしています。WORKDIRで以後、コマンドを実行するディレクトリを指定します。
COPY, RUN, CMDでパッケージをゲストOSにコピーし、yarn, yarn devを実行しています。
docker-compose.yml側で同じ設定をしているので、なくても大丈夫です。# ./nuxt-sample/Dockerfile FROM node:14.15.1-alpine3.12 WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install CMD ["yarn", "dev"]services: railsの設定
build, ports, volumesは先ほどと同じような意味です。
dockerでbinding.pryなどのデバッグができるように、
stdin_open: true
とtty: true
を指定しています。depends_onでは、mysqlを指定し、mysqlのコンテナが起動するまではrailsのコンテナが起動しないようにしています。
docker-compose.ymlrails: build: ./rails-sample ports: - 3000:3000 volumes: - ./rails-sample:/app - /app/node_modules stdin_open: true tty: true command: sh -c "yarn && bundle exec rails server -b 0.0.0.0 -p 3000" depends_on: - mysqlDockerfileの方もnuxtと同じように依存パッケージをインストールして、railsサーバーを起動しています。
# ./rails-sample/Dockerfile FROM ruby:2.7.1-alpine RUN set -x && apk add --no-cache \ # for mysql mysql-dev \ # for nokogiri build-base \ # for tzinfo-data tzdata \ yarn WORKDIR /app COPY Gemfile Gemfile.lock package.json yarn.lock ./ RUN bundle install RUN yarn install CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0"]database.ymlの設定
RailsサーバーとMySQLを接続するために、docker-compose.ymlのサービスで指定している名前をdatabase.ymlで設定する必要があります。
services: mysql
と設定していたので、database.ymlのhostにもmysqlと設定しておきます。database.ymldefault: &default adapter: mysql2 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default username: root password: database: rails-sample-dev host: mysql test: <<: *default username: root password: database: rails-sample-test host: mysqlnuxt.config.jsの設定
NuxtからRailsにプロキシしたい場合は、nuxt.config.jsのproxyにサービス名を記述するだけでプロキシできます。
nuxt.config.js... proxy: { '/api': 'http://rails:3000' }, ...おわりに
実際にコードを見ながら、動かしながら学んだ方が理解が深まると思うので、ぜひGitHubのリポジトリもご確認ください!
https://github.com/yassun-youtube/docker-compose-sample
- 投稿日:2020-11-29T17:12:48+09:00
docker-composeを使った開発環境構築実践! Rails + Nuxt + MySQL
はじめに
docker-composeを使ったローカル開発環境構築について解説します!
ここでは、フロントエンドにNuxt.js, バックエンドにRails, DBにMySQLを使った構成にします。
YouTube動画
動画で確認したい方はこちらもどうぞ!
【YouTube動画】 docker-compose による開発環境構築入門
GitHub
GitHubにコードを載せているので、実際に動かしてみたい方はこちらもどうぞ!
https://github.com/yassun-youtube/docker-compose-samplegit clone git@github.com:yassun-youtube/docker-compose-sample.git
実際のコード
docker-compose.ymlversion: "3.8" services: rails: build: ./rails-sample ports: - 3000:3000 volumes: - ./rails-sample:/app - /app/node_modules stdin_open: true tty: true command: sh -c "yarn && bundle exec rails server -b 0.0.0.0 -p 3000" depends_on: - mysql nuxt: build: ./nuxt-sample ports: - 8000:8000 volumes: - ./nuxt-sample:/app - /app/node_modules command: sh -c "yarn && yarn dev" mysql: image: mysql:8.0.22 volumes: - db-data:/var/lib/mysql environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: test-database volumes: db-data:# ./nuxt-sample/Dockerfile FROM node:14.15.1-alpine3.12 WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install CMD ["yarn", "dev"]# ./rails-sample/Dockerfile FROM ruby:2.7.1-alpine RUN set -x && apk add --no-cache \ # for mysql mysql-dev \ # for nokogiri build-base \ # for tzinfo-data tzdata \ yarn WORKDIR /app COPY Gemfile Gemfile.lock package.json yarn.lock ./ RUN bundle install RUN yarn install CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0"]database.ymldefault: &default adapter: mysql2 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default username: root password: database: rails-sample-dev host: mysql test: <<: *default username: root password: database: rails-sample-test host: mysqlnuxt.config.js... proxy: { '/api': 'http://rails:3000' }, ...
docker-composeとは
docker-composeとは複数コンテナやネットワーク、ボリュームを一括管理できるツールです。
Dockerをインストールすれば、ついてくるので、別途インストールする必要はありません。よく使うコマンド
docker-composeでよく使うコマンドを紹介します。
docker-compose up
docker-compose.ymlに記載されたコンテナを起動するために使います。
-d
オプションを付けると、デタッチモードで起動します。docker-compose down
起動したコンテナを停止して削除するときに使います。
削除しない場合は、CTRL + Cを押すかdocker-compose stop
で止めることができます。コンテナをデタッチモードで動かしているときは、
docker-compose ps
と併用して使います。docker-compose build
docker-compose.ymlに記載されたサービス (nuxtとかrails, mysql) をビルドするときに使います。
ymlファイル内のimage:
またはbuildに書かれているパスにあるDockerfileのイメージを参照して、ビルドを開始します。docker-compose run <サービス名> <コマンド>
docker-compose.ymlに記載されたサービスを指定してコマンドを実行するときに使います。
docker-compose exec <サービス名> <コマンド>
既に起動しているコンテナを指定して、コマンドを実行するときに使います。
docker-compose.ymlの概要
docker-compose.ymlで指定できる、
version
services
networks
volumes
について紹介します。version
docker-composeの書き方のバージョンを指定するときに使います。
この記事を書いている段階 (2020/11/29) では、3.8です。services
コンテナを定義するために使います。
ここで、railsとかnuxt, mysqlのDockerfileを指定したり、イメージを直接指定して使います。networks
各サービスがどのネットワークと接続するかを定義できます。
volumes
ホストOSとゲストOSでデータを同期するときに使います。
今回はMySQLのデータを同期するために使います。実際の設定ファイル
実際の設定ファイルは以下のようになります。
docker-compose.ymlversion: "3.8" services: rails: build: ./rails-sample ports: - 3000:3000 volumes: - ./rails-sample:/app - /app/node_modules stdin_open: true tty: true command: sh -c "yarn && bundle exec rails server -b 0.0.0.0 -p 3000" depends_on: - mysql nuxt: build: ./nuxt-sample ports: - 8000:8000 volumes: - ./nuxt-sample:/app - /app/node_modules command: sh -c "yarn && yarn dev" mysql: image: mysql:8.0.22 volumes: - db-data:/var/lib/mysql environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: test-database volumes: db-data:大枠の設定
上記設定ファイルの大枠をみていきます。
設定ファイルはバージョン3.8を利用し、サービスにはrails, nuxt, mysqlを指定しています。
DBのデータを同期するために、volumes: db-data:
を指定しています。docker-compose.ymlversion: "3.8" services: rails: ... nuxt: ... mysql: ... volumes: db-data:services: mysqlの設定
imageでMySQL 8.0.22のDockerイメージを取得し、volumesでデータを同期しています。
environmentで環境変数を設定でき、ここではrailsからROOTユーザーとして、アクセスできるようにしています。
また、作成するDB名はtest-databaseとしました。docker-compose.ymlmysql: image: mysql:8.0.22 volumes: - db-data:/var/lib/mysql environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: test-databaseservices: nuxtの設定
nuxtは別途Dockerfileを作成し、そこからイメージを取るようにしました。
Dockerfileの場所をbuildで指定しています。portsでは、ホストOSの8000ポートとゲストOSの8000ポートを繋げる設定をしています。
volumesの1行目
./nuxt-sample:/app
は、ホストOSのnuxt-sampleをゲストOSのappと同期するための設定です。
2行目の/app/node_modules
はホストOSのnode_moduleとゲストOSのnode_moduleを同期しないための設定です。
node_modulesはOS依存のパッケージが入る可能性があるので、このように除外しています。commandでは、コンテナ起動時にシェルで実行するコマンドを設定しています。
node_modulesを作るために、yarn
を実行し、yarn dev
でnuxtを起動しています。docker-compose.ymlnuxt: build: ./nuxt-sample ports: - 8000:8000 volumes: - ./nuxt-sample:/app - /app/node_modules command: sh -c "yarn && yarn dev"次にDockerfileをみていきます。
FROMで使用するDockerイメージを指定します。
開発環境なので、軽量なalpineにしています。WORKDIRで以後、コマンドを実行するディレクトリを指定します。
COPY, RUN, CMDでパッケージをゲストOSにコピーし、yarn, yarn devを実行しています。
docker-compose.yml側で同じ設定をしているので、なくても大丈夫です。# ./nuxt-sample/Dockerfile FROM node:14.15.1-alpine3.12 WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install CMD ["yarn", "dev"]services: railsの設定
build, ports, volumesは先ほどと同じような意味です。
dockerでbinding.pryなどのデバッグができるように、
stdin_open: true
とtty: true
を指定しています。depends_onでは、mysqlを指定し、mysqlのコンテナが起動するまではrailsのコンテナが起動しないようにしています。
docker-compose.ymlrails: build: ./rails-sample ports: - 3000:3000 volumes: - ./rails-sample:/app - /app/node_modules stdin_open: true tty: true command: sh -c "yarn && bundle exec rails server -b 0.0.0.0 -p 3000" depends_on: - mysqlDockerfileの方もnuxtと同じように依存パッケージをインストールして、railsサーバーを起動しています。
# ./rails-sample/Dockerfile FROM ruby:2.7.1-alpine RUN set -x && apk add --no-cache \ # for mysql mysql-dev \ # for nokogiri build-base \ # for tzinfo-data tzdata \ yarn WORKDIR /app COPY Gemfile Gemfile.lock package.json yarn.lock ./ RUN bundle install RUN yarn install CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0"]database.ymlの設定
RailsサーバーとMySQLを接続するために、docker-compose.ymlのサービスで指定している名前をdatabase.ymlで設定する必要があります。
services: mysql
と設定していたので、database.ymlのhostにもmysqlと設定しておきます。database.ymldefault: &default adapter: mysql2 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default username: root password: database: rails-sample-dev host: mysql test: <<: *default username: root password: database: rails-sample-test host: mysqlnuxt.config.jsの設定
NuxtからRailsにプロキシしたい場合は、nuxt.config.jsのproxyにサービス名を記述するだけでプロキシできます。
nuxt.config.js... proxy: { '/api': 'http://rails:3000' }, ...おわりに
実際にコードを見ながら、動かしながら学んだ方が理解が深まると思うので、ぜひGitHubのリポジトリもご確認ください!
https://github.com/yassun-youtube/docker-compose-sample
- 投稿日:2020-11-29T14:34:03+09:00
Cloud Native Ecosystemの成熟度から見る2021年の動向
記事を書いたきっかけとお詫び
- Kubernetesとそのエコシステムが実に幅広く、知れば知るほど何もわからなくなってしまいました
- Kubernetes自体は使用してみて1年弱ですが、今後何をどこまで深堀りしていくか取捨選択が必要になってきたため、成熟度の観点とトレンドを基に2021年に何をしようか考えてみることにした
- 特にCNCF自体も宣言している通りプロジェクトの統廃合も進む年になるので、少し俯瞰して考えてみる
- 余談として、コミュニティとの関わりなど個人的な期待を備忘的に残すことにした
※普段アウトプットが少ないにもかかわらず初めてAdvent Calendarを書くため、大きなテーマを取り上げてしまったことを反省しています。こんなこと考えている人もいるんだな、くらいの温度感で読んでいただけるとよきです。同じような境遇の方などの参考に少しでもなれば幸いです。
Kubernetesとクラウドネイティブの現状
- KubeConでもKubernetes自体のアップデートより、CNCF Landscapeを中心とした周辺技術の活性化の方が注目されてきた
- 一方で、エンタープライズにおいてはKubernetesやDockerは「VMからコンテナ化して軽量化」という文脈で語られることが未だ少なくない印象で、クラウドネイティブ化という大きなパラダイムシフトの観点が欠けているケースが散見される。今まさに各社では文化や意識の改革を迫られ、キャズムが発生している状態である。
- クラウドネイティブエコシステムについて、何をどの程度深堀すべきかは未だ流動的な状態である。
Kubernetesとキャズム越え
技術採用のライフサイクル(Technology Adaption Lifecycle)の図でいうと、Kubernetesはキャズムを越えるか、超えないかというステータスであるという意見が昨年ごろから散見された。
越えたか越えてないかはさほど重要でなく、現状のトレンドを見る限り多くの人がKubernetesを活用していくことに対して否定的な意見は多くない状況かと思う。
参考: https://medium.com/@shivayogiks/what-is-technology-adoption-life-cycle-and-chasm-e07084e7991f
上記とは別にCNCFもMaturity Levels(成熟度合い)を定義しており、CNCF ProjectとしてIncubatingからGraduatedになったものはキャズムを越えていると定義している。
参考: https://www.cncf.io/projects/
KubernetesとEcosystemに関するキャズム
CNCF Landscapeの変遷
KubernetesのEcosystemは、Cloud NativeなプロダクトであるCNCF Lanscapeとしてある程度表現されていると捉えられる。
Cloud Nativeなプロジェクトを記載したCNCF Landscapeは最早豆粒のようなものしか見えない程度にまで成長し、全てのカテゴリで新しい製品が作り出され続けている。
この中でも特に、成熟度が高いGraduatedなプロジェクトの変遷をみてみる。
CNCF Graduated Projects
- 2020/12/4現在、13のProjectがGraduatedとなっている。
参考: https://www.cncf.io/projects/
Graduated Project認定時期
この3年弱でGraduatedとなったプロジェクトを時系列でまとめてみた。
OPA, CRI-Oに関しては、近々Graduateするとのことだったため時期未定で追加した。
参考: https://github.com/cncf/toc/projects
2020年以前にGraduatedとなった9 Projects
2020以前にGraduatedになった9 Project
2018/03/06 kubernetes
https://www.cncf.io/blog/2018/03/06/kubernetes-first-cncf-project-graduate/
2018/08/09 prometheus
https://www.cncf.io/announcements/2018/08/09/prometheus-graduates/
2018/11/28 envoy
https://www.cncf.io/announcements/2018/11/28/cncf-announces-envoy-graduation/
2019/1/24 coredns
https://www.cncf.io/announcements/2019/01/24/coredns-graduation/
2019/2/28 containerd
https://www.cncf.io/announcements/2019/02/28/cncf-announces-containerd-graduation/
2019/04/11 fluentd
https://www.cncf.io/announcements/2019/04/11/cncf-announces-fluentd-graduation/
2019/10/31 jaeger
2019/11/5 vitess
2019/12/18 tuf
2020年にGraduatedとなった5 Projects
2020年にGraduatedとなった5 Projects
Helm - Packaging Manager
2020/4/30
Harbor - Cloud native registry
2020/6/23
TiKV - Cloud native key-value database
2020/9/30
Rook - Cloud native storage tool
2020/10/7
etcd - distributed, reliable key-value store
2020/11/24
標準化やコンパティビリティ
Kubernetesのエコシステムは様々な標準化によって支えられていて、CRI, CNI, CSI, SMI, OpenTelemetryなどがある。
標準化されたインタフェースを把握することで枝葉の部分の各プロダクトを厳密に理解しなくてはよいため、興味の対象を絞ることができる。もちろん運用をする場合はさらに詳しく見ていく必要はあることは間違いない。
一方でここであげているインタフェースに関してもあくまで一部でしかないが、これらを体系的にまとめた資料などは見つけられていない。
また、運用のトイルを減らすべく、Kubernetes Operatorも活用例が増えてきている。
Operator作成に用いるツールに関してもoperator-sdk, kubebuilderがあったが、2020/7に実質の統合が行われoperator-sdk側が事実上のスタンダードとなった。詳細は下記にまとめている。
【Kubernetes Operator】operator-sdkとkubebuilder統合に関する注意点 - Qiita
また、operator-sdkが含まれるOperator Frameworkは同じ2020/7にCNCF Incubating Projectになっている。Operatorを作るほど体力がないケースがほとんどと思われるため、Operatorをどこまで突き詰められるかは環境に依存するところが大きそう。
下記の記事でも少しだけ触れている。
Kubernetes Internal #2に参加してみた - Qiita
Kubernetes界隈の今後の予測
※ここまでで述べた事実に基づき、ここからは個人的な推測混じりの感想と展望を記載します。
個人的な期待や予測
Kubernetesやエコシステムの今後
KubeCon NA 2020にて述べられた通り、Sandbox Projectとして承認される敷居が下がるため、Sandbox Projectの統廃合が進むことが示された。これはつまりGraduated, Incubatingの指す意味が今までより一層MatureなProjectであることを裏付けてくれる。
その意味では、今後はよりIncubatingとGraduatedに焦点を当ててキャッチアップしていく戦略が求められそう。下記のCNCFのページにもその2カテゴリがリストされている。
KubeCon NA Virtual 2020における、Graduated, Incubatingの講演
文字なしで画像だけですべてのGraduated, Incubatingを紹介してくれる貴重な資料なのでこちらも参考になる
講演資料: https://static.sched.com/hosted_files/kccncna20/a9/Carson-Anderson_CNCF-Flyover.pdf
コミュニティ活動の今後
Meetupもコロナによってあり方が大きく変わった。仕事終わりに会場まで足を運び、現地で軽食をつまみながら現地の空気感を味わえる体験は、リモートのそれと比較すると両方に良さがあるように思う。詳細は別記事で別途まとめることとするが、リモート化したMeetupの体験をよりよくする動きは今後も継続して模索されていくと期待できる。
初学者向けのMeetupもできてはいるが、偉大な先人が数年前に作成した資料がすでにゴロゴロ存在していたりするため、内容はより事例や詳細、エコシステム群などに特化していくことが予想される。
過去の良い資料などが再利用性を高めて保持されたり、登壇自体が目的とならないように、コミュニティ活動のスタイルが変わったりというような変遷が来年にかけて起こっていくといいな、という期待がある。
ここに関するコミュニティ活動改善のアイデアは別途まとめて、フィードバックをもらえる場所で公開したい。
企業におけるクラウドネイティブ
旧来型のアジリティではアップデートに追従するだけで、相当な体力が必要なことは各企業で叫ばれている。
今後ますます塩漬けは厳しくなっていくと予想していたが、先日のKubeCon NA 2020にてCNCF Projectのリリースライフサイクルを低下させる提案が発表された。これは、各企業でアップデートに追従できていないことを示唆している。
Cloud NativeなProjectがより採用されやすくなることで、Late Majorityをうまく引き込むための歩み寄りと捉えることができる。一方で、旧来の塩漬け運用に逆行するわけでないことは改めて認識しなければいけない。
2021年の注目技術
KubeCon NA 2020にて、2021年に注目する技術として紹介された5つの技術が下記である。
今後どのように発展していくか注目していく必要がありそう。
- Chaos Engineering
- Kubernetes Edge
- Service Mesh
- WASM and eBPF
- Developer & Operator Experience
このうち、Chaos Engineering FrameworkのLitmusについては下記の記事にてまとめた。
https://qiita.com/iaoiui/items/00369f232a23d2e30b2c
まとめ
Kubernetesは2年前のKubeConの時点でboring(退屈)と言われていたように、KubeConはエコシステム側への考慮がより深まって行っている状況である。
現状はKubernetesとクラウドネイティブの潮流はキャズムを迎え、より幅広い層に利用されていく過程にある。
その一方でエコシステム自体は拡大を続けているため、現状のアーリーアダプターや市場がどのような方向にシフトしていくかを注視していくことがますます重要になる。
特に、CNCFが2021年に注目する技術である、下記の5点は今後の方向性を見定めていく必要がある。
- Chaos Engineering
- Kubernetes Edge
- Service Mesh
- WASM and eBPF
- Developer & Operator Experience
また、1つの指標としてCNCF Graduated, Incubating Projectを基に、成熟したプロジェクトの変遷を改めて振り返り今後の傾向予測の参考とした。
今後何を学んでいくべきか迷った時に振り返ろうと思う。
- 投稿日:2020-11-29T13:50:23+09:00
Dockerを使って最速で社内DNSを構築してみた
この記事は 生産性向上のための環境整備2020 【PR】 Lenovo Advent Calendar 2020 の1日目の記事です。
2日目の記事:未定
社内だけで使えるサービスやシステムを複数運営していると、IPアドレスでのアクセスは大変になってきます。
そこで、社内サービスにもドメインを使ってアクセスできるように社内DNSを整備しました。
前提
- ドメインは取得済み
- ドメインのワイルドカード証明書取得済み
→ これに関しては取得していなくても大丈夫ですが、SSL化された通信を行いたい場合は取得しておきましょう
- 取得ドメイン:choipre.com
構築
DNSはDockerを使って構築します。CoreDnsというDocker-imageが公開されているので、そちらを利用します。フォルダ構成としては以下の感じです。
drwxr-xr-x - nomunomu 2 11 18:01 dns .rw-r--r-- 244 nomunomu 4 11 16:00 ├── docker-compose.yml .rw-r--r-- 115 nomunomu 4 11 16:00 ├── Dockerfile drwxr-xr-x - nomunomu 2 11 17:58 └── volumes drwxr-xr-x - nomunomu 4 11 16:14 └── config .rw-r--r-- 181 nomunomu 4 11 16:32 ├── Corefile .rw-r--r-- 53 nomunomu 4 11 16:14 └── hostsDocker系設定
docker-compose.ymlversion: '3.1' services: coredns: build: . container_name: coredns restart: on-failure expose: - '53' - '53/udp' ports: - '53:53' - '53:53/udp' volumes: - './volumes/config:/etc/coredns'DockerfileFROM coredns/coredns:1.7.0 EXPOSE 53 EXPOSE 53/udp ENTRYPOINT ["/coredns"] CMD ["-conf", "/etc/coredns/Corefile"]CoreDns設定
どのドメインとIPアドレスが紐づくかをhostsファイルに記述します。Corednsの設定はファイルはCorefileというファイルに記述します。
Corefile. { whoami forward . 192.168.0.100:53 # ここはPublic-DNSでもよい errors log . "{proto} {remote} is Request: {name} {type} {>id}" hosts /etc/coredns/hosts { fallthrough } reload }hosts192.168.0.110 xxxxxx.choipre.com 192.168.0.111 yyyyyy.choipre.com 192.168.0.112 zzzzzz.choipre.com起動
docker-compose.ymlがあるディレクトリで以下のコマンドを流すと、DNSが起動します。
docker-compose updocker-composeを走らせたPC(192.168.0.100)へ各クライアントのDNS解決先を向けることでローカルのIPに対してもドメインでアクセスすることができるようになります。
社内のネットワークを整備して、快適なネットワークLifeを!!
- 投稿日:2020-11-29T13:50:23+09:00
docker-composeを使って最速で社内DNSを構築してみた
この記事は 生産性向上のための環境整備2020 【PR】 Lenovo Advent Calendar 2020 の1日目の記事です。
2日目の記事:未定
社内だけで使えるサービスやシステムを複数運営していると、IPアドレスでのアクセスは大変になってきます。
そこで、社内サービスにもドメインを使ってアクセスできるように社内DNSを整備しました。
前提
- ドメインは取得済み
- ドメインのワイルドカード証明書取得済み
→ これに関しては取得していなくても大丈夫ですが、SSL化された通信を行いたい場合は取得しておきましょう
- 取得ドメイン:choipre.com
構築
DNSはDockerを使って構築します。CoreDnsというDocker-imageが公開されているので、そちらを利用します。フォルダ構成としては以下の感じです。
drwxr-xr-x - nomunomu 2 11 18:01 dns .rw-r--r-- 244 nomunomu 4 11 16:00 ├── docker-compose.yml .rw-r--r-- 115 nomunomu 4 11 16:00 ├── Dockerfile drwxr-xr-x - nomunomu 2 11 17:58 └── volumes drwxr-xr-x - nomunomu 4 11 16:14 └── config .rw-r--r-- 181 nomunomu 4 11 16:32 ├── Corefile .rw-r--r-- 53 nomunomu 4 11 16:14 └── hostsDocker系設定
docker-compose.ymlversion: '3.1' services: coredns: build: . container_name: coredns restart: on-failure expose: - '53' - '53/udp' ports: - '53:53' - '53:53/udp' volumes: - './volumes/config:/etc/coredns'DockerfileFROM coredns/coredns:1.7.0 EXPOSE 53 EXPOSE 53/udp ENTRYPOINT ["/coredns"] CMD ["-conf", "/etc/coredns/Corefile"]CoreDns設定
どのドメインとIPアドレスが紐づくかをhostsファイルに記述します。Corednsの設定はファイルはCorefileというファイルに記述します。
Corefile. { whoami forward . 192.168.0.100:53 # ここはPublic-DNSでもよい errors log . "{proto} {remote} is Request: {name} {type} {>id}" hosts /etc/coredns/hosts { fallthrough } reload }hosts192.168.0.110 xxxxxx.choipre.com 192.168.0.111 yyyyyy.choipre.com 192.168.0.112 zzzzzz.choipre.com起動
docker-compose.ymlがあるディレクトリで以下のコマンドを流すと、DNSが起動します。
docker-compose updocker-composeを走らせたPC(192.168.0.100)へ各クライアントのDNS解決先を向けることでローカルのIPに対してもドメインでアクセスすることができるようになります。
社内のネットワークを整備して、快適なネットワークLifeを!!
- 投稿日:2020-11-29T13:31:42+09:00
Dockerのバージョン確認方法
- 投稿日:2020-11-29T13:16:49+09:00
Flutterをとりあえず試してみたい人向け
この記事について
- 最近Flutterを聞くけど、あんまり環境を汚したくないという人向けにFlutterのweb環境構築を用意しました
- dockerを使います
- vscodeを(必ず)使います
- dockerでflutter for webなので、windowsでもmacでもokです
- ひとまず試したい人向けに書いているので、パッケージの永続化とかはしていませんし、本格的にやるならばローカルにきちんと構築するべきだと思います
- リポジトリ
やること
- リポジトリをクローン
docker-compose build
docker-compose up -d workspace
- vscodeのremote-container機能でworkspaceコンテナを開きます
flutter create .
flutter run
- chromeを開きながらコーディング!
詳しく
上の説明でわかればもう読まなくて十分です。
まず、dockerを使う必要があるので、dockerのインストールと基本的なことは終わらせておいてください。
その後、コンテナのイメージをbuild
でビルドし、コンテナをup -d
で作成します。ここからが重要なのですが、
flutter run
するときは必ずvscodeのremote-containerでコンテナに入った状態でflutter run
してください。そうしないと、localhostでうまく接続できません。最後に、開発を終了したい時は
Ctrl+C
でserverを停止してdocker-compose down
でコンテナ停止&削除して終了です。終わり
最近流行りのFlutterをとりあえず試してみたい人は使ってみてください
- 投稿日:2020-11-29T12:30:49+09:00
Cloudflare + Dockerで自動更新可能ワイルドカード証明書を発行して社内サービスをSSL化してみた
この記事は 生産性向上のための環境整備2020 【PR】 Lenovo Advent Calendar 2020 の3日目の記事です。
2日目の記事:腰痛のためのリマインダー機能 by @ryu3
4日目の記事:エンジニアのための目を休ませる最高の環境 @newt0Chromeでhttpサイトが見れなくなる??
Chromeの開発元であるGoogleは以下のような声明を出しました。
(引用元: https://security.googleblog.com/2019/10/no-more-mixed-messages-about-https_3.html)Today we’re announcing that Chrome will gradually start ensuring that https:// pages can only load secure https:// subresources. In a series of steps outlined below, we’ll start blocking mixed content (insecure http:// subresources on https:// pages) by default. This change will improve user privacy and security on the web, and present a clearer browser security UX to users.
本日、Chrome では、https:// ページが安全な https:// サブリソースのみを読み込むことができるようにすることを段階的に開始することを発表しました。以下に概説する一連の手順で、混合コンテンツ ( https:// ページの安全でない http:// サブリソース) をデフォルトでブロックするようになります。この変更により、ウェブ上でのユーザーのプライバシーとセキュリティが改善され、より明確なブラウザセキュリティUXをユーザーに提示することができます。
混合コンテンツ
混合コンテンツとは、https内に存在するhttpなコンテンツのことを指します。
つまり「https://xxxxxxxxx.com/」というセキュアなサイト内で「http://yyyyyyyyyyy.com/image/test.png」のようなセキュアでないコンテンツを呼び出している状態を意味します。つまり、httpなサイトはChromeで閲覧できなくなる可能性があるということです。
さらにこの問題が顕著なのは、日本におけるChromeの利用率が高いという点です。
(参照元: https://lab.syncer.jp/Statistic/Browser/2019/10/)・ デスクトップのシェア:66.14%(1位) ・ モバイルのシェア:26.46%(2位) ・ タブレットのシェア:36.56%(2位)社内だけのサービス(退勤管理やソース管理など)だからといって、セキュア化していないとアクセスできない。なんてことにならないように社内のネットワーク整備をすることにしました。
では、社会人1年目、新卒入社の筆者が社内ネットワーク整備に奮闘した一部始終をどうぞ!!
環境
- CentOS 7
→ 社内サービスがDocker on CentOS7で動いてた- Let's Encrypt
→ 無料で使えるSSL証明書。90日で期限が切れるため更新が必須- Cloudflare
→ ワイルドカード証明書を発行するのにDNSレコードを変更する必要があるため、無料で使えるCloudflareを採用。(このためだけにNSを変更したといっても過言ではない)- lego(https://go-acme.github.io/lego/)
→ Let's Encryptの環境がさくっと作れるDocker環境。大体のDNS Providerに対応してて、それぞれの設定方法や実行方法が書いてあってありがたい。 (対応してるDNS Provider一覧はこちら)改修フロー
https化へのざっくりとしたフローはこちらです。
- 社内サービスへのアクセスをサブドメインで行えるようにする
- ドメインのネームサーバー(NS)をCloudflareに変更
- Cloudflareでソーン編集用APIアクセスキーを作成
- 社内サービスコンテナ内で自動更新スクリプト等の作成
- Nginxなどに証明書を食わせる
今回は検証用の個人的なドメイン(choipre.com)(Google Domains)を使って解説します。
ドメイン取ったけど、個人サービスが完成していないので、何しても大丈夫だし。!! 注意 !!
設定を間違えるとサイトにアクセスできなくなったりする可能性があります。必ず変更点(Diff)などはメモするようにしておいた方が、万が一のためです。バックアップなどを取りつつ作業を進めることをおすすめします。1. 社内サービスへのアクセスをサブドメインで行えるようにする
これまで、社内サービスにはIPアドレスを使ってアクセスしていました。そのためhttps化できず、httpな状態で運用していました。まずは、社内サービスへのアクセスをサブドメインでアクセスできるようにするため、社内DNSを整備します。ドメインは、会社HPなどで元々利用しているものを利用しました。その内容は別記事として割愛します。
2. ドメインのNSをCloudflareに変更
なぜCloudflareに変更したかというと、CloudflareではAPIを使ってドメインのゾーン情報(A, AAAA, TXTなどのDNSレコード情報)を書き換えることができます。
(参考: https://api.cloudflare.com/#zone-subscription-zone-subscription-details)この仕組みを利用して、スクリプト上でワイルドカードのSSL証明書を発行するのに必要なレコード内容を自動で書き込みたかったからです。
(証明書更新する度に手動でDNSレコードに追記したり、削除したりするのって面倒だし、ネットワークの知識がない人が更新しないといけないってなったときに、このコマンド一発叩けばいいよ!の方がいいよね?)Cloudflareにドメインを登録
Cloudflareのアカウントを持っていない人はアカウント作成してください。
アカウント作成後、トップ画面に 【サイトを追加する】 を押します。
(※ 画像は既に登録済みのドメインがあるため、Cloudflareの管理下にあるドメイン一覧がありますが、初期登録後の人は何も表示されていません。)
プラン選択画面が表示されるので 【Freeプラン】 を選択します。
(Freeプランでここまで出来るってCloudflare様様...)
Cloudflareに既存DNSレコードを移植
ドメインの登録が完了すると、現在設定されているDNSレコードを読み取って、Cloudflareに書き込み準備をしてくれます。このときにDNSレコードを修正することもできますが、必要がない人はそのまま 【続行】 します。
ただし、AレコードとMXレコードが同一の場合、AレコードをCloudflareのプロキシから外す必要があります。プロキシから外してDNS解決のみにしないとメールサーバーが正常に動作しないためです。
(参考: Cloudflareの使用時にメールが配信不能になる - メール関連のDNSレコード)
CloudflareのNSに変更する
Cloudflareに取り込むDNSレコードの設定が終わったら、ドメインのNSをCloudflareに変更するように促されます。
各ドメインの管理画面からドメインのNSを変更します。今回の検証用ドメインはGoogle Domainsで取得しているため、Google Domainsの設定画面から変更します。
ドメインのNS変更が終わったら、Cloudflareで引き続き設定を行います。ここでは、ドメインへのアクセス、コンテンツのキャッシュ・圧縮設定ができます。利用に応じた設定を行ってください。
Cloudflare-NSの変更チェック
次にNSレコードのチェックをします。既にNSの変更が検知できている場合は、以下のような表示になります。
まだ、検知できていない場合は以下のような表示になります。ドメインの設定がネットワーク全体に浸透するまでは24~48時間程かかります。Cloudflareでチェックしても変更されていなかった場合は、少し時間をおいてください。ちなみに、Cloudflareで正常にNSが変更されていることを検知すると、アカウント登録時に設定したメールアドレスに通知がきます。
3. ソーン編集用APIアクセスキーを作成
legoのライブラリを利用するために必要な、CloudflareのDNSゾーン情報APIアクセスキーを作成します。キーは2種類作成します。
ゾーン情報の【DNS編集キー】と【ゾーン編集キー】です。Cloudflareのアカウント設定のAPIトークンから作成することができます。
まず、APIアクセスキーを作成する前に、画面下部にある「Global Api key」も取得しておきましょう。4.のdocker-compose.ymlに記述する必要があるためです。
アクセスキーを作成する際に、いくつかテンプレートが用意されています。今回は【ゾーンDNSを編集する】というテンプレートを編集して利用します。テンプレートを利用せずに0から作成することもできますが、慣れてから使うか、似たテンプレートを変更したほうが無難そうです。
1つのトークンに対して、複数の権限を付与することができますが、トークンが増えてくると管理がしづらくなるので、1トークン1権限で運用することとします。アクセス許可に以下を、それぞれ設定して2つのトークンを作成します。
- 1つ目のトークン
→ ゾーン:DNS:編集- 2つ目のトークン
→ ゾーン:ゾーン:編集- 2つの共通設定(ゾーンリソース)
→ 包含:特定のゾーン:ワイルドカード証明書を発行したいドメイントークン作成を進めると、以下のような画面が表示されます。このときに表示されるトークンをメモしてください。ここで表示されたトークンは、画面にもあるように再表示されません。そのため、必ずメモするようにしてください。メモし忘れたら、APIトークンを削除して、再作成してください。
4. SSL証明書の自動更新スクリプトの作成
会社の社内サービスが動いているDockerでは、以下のような運用がされています。
- 平日(月〜金)は昼夜問わず常時起動
- 休日(土日)に自動シャットダウン
- 月曜にサービスを立ち上げる
このことから、サービスを立ち上げるときにSSL証明書の更新処理を走るようにしておけば、最低週に1回は確認することになり、更新忘れによる証明書失効を防ぐことが出来ると考えました。サービス自体がDockerで運用されているため、SSL更新処理もDocker化して、Serviceとして登録する方向にしました。
lego(https://go-acme.github.io/lego/)を使ったSSL証明書更新用Dockerは以下のように設定しました。
docker-compose.ymlservices: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos run volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてくださいdocker-compose.yml を作成して、docker-composeを実行します。
$ docker-compose up実行が終わると、以下のようなログが流れ、
/opt/cert
配下に証明書本体が格納されているディレクトリと、更新に必要なアカウント情報が含まれているディレクトリが生成されます。❯ docker-compose up Recreating certbot-cloudflare_certbot-lego_1 ... done Attaching to certbot-cloudflare_certbot-lego_1 certbot-lego_1 | 2020/11/28 06:44:01 [INFO] acme: Registering account for [Cloudflareに登録したメールアドレス] certbot-lego_1 | !!!! HEADS UP !!!! certbot-lego_1 | certbot-lego_1 | Your account credentials have been saved in your Let's Encrypt certbot-lego_1 | configuration directory at "/lego/accounts". certbot-lego_1 | certbot-lego_1 | You should make a secure backup of this folder now. This certbot-lego_1 | configuration directory will also contain certificates and certbot-lego_1 | private keys obtained from Let's Encrypt so making regular certbot-lego_1 | backups of this folder is ideal. certbot-lego_1 | 2020/11/28 06:44:01 [INFO] [*.choipre.com, choipre.com] acme: Obtaining bundled SAN certificate certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315819 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315820 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] acme: use dns-01 solver certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: tls-alpn-01 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: http-01 (省略) certbot-lego_1 | 2020/11/28 06:44:11 [INFO] [*.choipre.com, choipre.com] acme: Validations succeeded; requesting certificates certbot-lego_1 | 2020/11/28 06:44:12 [INFO] [*.choipre.com] Server responded with a certificate. certbot-cloudflare_certbot-lego_1 exited with code 0drwxr-xr-x - nomunomu 28 11 15:43 └── opt drwxr-xr-x - nomunomu 28 11 15:44 └── cert drwx------ - nomunomu 28 11 15:43 ├── accounts drwx------ - nomunomu 28 11 15:43 │ └── acme-v02.api.letsencrypt.org drwx------ - nomunomu 28 11 15:44 │ └── xxxxxxxxxxx@gmail.com .rw------- 225 nomunomu 28 11 15:44 │ ├── account.json drwx------ - nomunomu 28 11 15:43 │ └── keys .rw-r--r-- 227 nomunomu 28 11 15:43 │ └── xxxxxxxxxx@gmail.com.key drwx------ - nomunomu 28 11 15:44 └── certificates .rw------- 3.3k nomunomu 28 11 15:44 ├── _.choipre.com.crt .rw------- 1.6k nomunomu 28 11 15:44 ├── _.choipre.com.issuer.crt .rw------- 234 nomunomu 28 11 15:44 ├── _.choipre.com.json .rw------- 227 nomunomu 28 11 15:44 └── _.choipre.com.keyこの生成されたフォルダで、accountsフォルダは今後証明書を更新していくなかで必要になるフォルダです。証明書類はcertificatesに保管されています。
「_.choipre.com.crt」がchoipre.comのワイルドカード証明書になります。一度、証明書発行を実行したので、今後は更新という処理を行う設定にしておく必要があります。そのため、docker-compose.ymlを以下のように変更します。
services: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos renew --days 30 volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてください変更点は、
run
からrenew
コマンドに変更することです。パラメーターとして--days
を指定することで指定した日数を切ってから更新させることができます。この、docker-composeの実行をcronなどに設定することで自動更新を行えるようになります。
5. ワイルドカードをnginxに適用する
4.で生成した証明書をNginxに適用していきます。証明書類は/opt/cert配下にあるものとします。Nginxの設定ファイルに以下の記述を追加します。
追記場所はNginxの設定ファイルの使用したいServer設定の中です。デフォルト構成を利用している人はserver{ ... }
の中に記述します。ssl_certificate /opt/cert/_.choipre.com.crt; ssl_certificate_key /opt/cert/_.choipre.com.key;記述ができたら、Nginxのプロセスを再起動します。Nginxのプロセスを再起動したら、対象のアドレスに対してhttpsアクセスをすると証明書が適用されていることが分かります。
まとめ
以上で、自動更新可能なワイルドカード証明書発行の実装が終わりました。
初期設定は大変ですが、今後はあらゆるサブドメインに対してSSL通信を行うことができます。これでChromeでhttpコンテンツが閲覧できなくなっても、安心ですね。生産性を向上してHappy Lifeを!!
- 投稿日:2020-11-29T12:30:49+09:00
Cloudflare + Dockerを使った自動更新可能ワイルドカード証明書で社内サービスをSSL化してみた
この記事は 生産性向上のための環境整備2020 【PR】 Lenovo Advent Calendar 2020 の3日目の記事です。
2日目の記事:腰痛のためのリマインダー機能 by @ryu3
4日目の記事:エンジニアのための目を休ませる最高の環境 @newt0Chromeでhttpサイトが見れなくなる??
Chromeの開発元であるGoogleは以下のような声明を出しました。
(引用元: https://security.googleblog.com/2019/10/no-more-mixed-messages-about-https_3.html)Today we’re announcing that Chrome will gradually start ensuring that https:// pages can only load secure https:// subresources. In a series of steps outlined below, we’ll start blocking mixed content (insecure http:// subresources on https:// pages) by default. This change will improve user privacy and security on the web, and present a clearer browser security UX to users.
本日、Chrome では、https:// ページが安全な https:// サブリソースのみを読み込むことができるようにすることを段階的に開始することを発表しました。以下に概説する一連の手順で、混合コンテンツ ( https:// ページの安全でない http:// サブリソース) をデフォルトでブロックするようになります。この変更により、ウェブ上でのユーザーのプライバシーとセキュリティが改善され、より明確なブラウザセキュリティUXをユーザーに提示することができます。
混合コンテンツ
混合コンテンツとは、https内に存在するhttpなコンテンツのことを指します。
つまり「https://xxxxxxxxx.com/」というセキュアなサイト内で「http://yyyyyyyyyyy.com/image/test.png」のようなセキュアでないコンテンツを呼び出している状態を意味します。つまり、httpなサイトはChromeで閲覧できなくなる可能性があるということです。
さらにこの問題が顕著なのは、日本におけるChromeの利用率が高いという点です。
(参照元: https://lab.syncer.jp/Statistic/Browser/2019/10/)・ デスクトップのシェア:66.14%(1位) ・ モバイルのシェア:26.46%(2位) ・ タブレットのシェア:36.56%(2位)社内だけのサービス(退勤管理やソース管理など)だからといって、セキュア化していないとアクセスできない。なんてことにならないように社内のネットワーク整備をすることにしました。
では、社会人1年目、新卒入社の筆者が社内ネットワーク整備に奮闘した一部始終をどうぞ!!
環境
- CentOS 7
→ 社内サービスがDocker on CentOS7で動いてた- Let's Encrypt
→ 無料で使えるSSL証明書。90日で期限が切れるため更新が必須- Cloudflare
→ ワイルドカード証明書を発行するのにDNSレコードを変更する必要があるため、無料で使えるCloudflareを採用。(このためだけにNSを変更したといっても過言ではない)- lego(https://go-acme.github.io/lego/)
→ Let's Encryptの環境がさくっと作れるDocker環境。大体のDNS Providerに対応してて、それぞれの設定方法や実行方法が書いてあってありがたい。 (対応してるDNS Provider一覧はこちら)改修フロー
https化へのざっくりとしたフローはこちらです。
- 社内サービスへのアクセスをサブドメインで行えるようにする
- ドメインのネームサーバー(NS)をCloudflareに変更
- Cloudflareでソーン編集用APIアクセスキーを作成
- 社内サービスコンテナ内で自動更新スクリプト等の作成
- Nginxなどに証明書を食わせる
今回は検証用の個人的なドメイン(choipre.com)(Google Domains)を使って解説します。
ドメイン取ったけど、個人サービスが完成していないので、何しても大丈夫だし。!! 注意 !!
設定を間違えるとサイトにアクセスできなくなったりする可能性があります。必ず変更点(Diff)などはメモするようにしておいた方が、万が一のためです。バックアップなどを取りつつ作業を進めることをおすすめします。1. 社内サービスへのアクセスをサブドメインで行えるようにする
これまで、社内サービスにはIPアドレスを使ってアクセスしていました。そのためhttps化できず、httpな状態で運用していました。まずは、社内サービスへのアクセスをサブドメインでアクセスできるようにするため、社内DNSを整備します。ドメインは、会社HPなどで元々利用しているものを利用しました。その内容は別記事として割愛します。
2. ドメインのNSをCloudflareに変更
なぜCloudflareに変更したかというと、CloudflareではAPIを使ってドメインのゾーン情報(A, AAAA, TXTなどのDNSレコード情報)を書き換えることができます。
(参考: https://api.cloudflare.com/#zone-subscription-zone-subscription-details)この仕組みを利用して、スクリプト上でワイルドカードのSSL証明書を発行するのに必要なレコード内容を自動で書き込みたかったからです。
(証明書更新する度に手動でDNSレコードに追記したり、削除したりするのって面倒だし、ネットワークの知識がない人が更新しないといけないってなったときに、このコマンド一発叩けばいいよ!の方がいいよね?)Cloudflareにドメインを登録
Cloudflareのアカウントを持っていない人はアカウント作成してください。
アカウント作成後、トップ画面に 【サイトを追加する】 を押します。
(※ 画像は既に登録済みのドメインがあるため、Cloudflareの管理下にあるドメイン一覧がありますが、初期登録後の人は何も表示されていません。)
プラン選択画面が表示されるので 【Freeプラン】 を選択します。
(Freeプランでここまで出来るってCloudflare様様...)
Cloudflareに既存DNSレコードを移植
ドメインの登録が完了すると、現在設定されているDNSレコードを読み取って、Cloudflareに書き込み準備をしてくれます。このときにDNSレコードを修正することもできますが、必要がない人はそのまま 【続行】 します。
ただし、AレコードとMXレコードが同一の場合、AレコードをCloudflareのプロキシから外す必要があります。プロキシから外してDNS解決のみにしないとメールサーバーが正常に動作しないためです。
(参考: Cloudflareの使用時にメールが配信不能になる - メール関連のDNSレコード)
CloudflareのNSに変更する
Cloudflareに取り込むDNSレコードの設定が終わったら、ドメインのNSをCloudflareに変更するように促されます。
各ドメインの管理画面からドメインのNSを変更します。今回の検証用ドメインはGoogle Domainsで取得しているため、Google Domainsの設定画面から変更します。
ドメインのNS変更が終わったら、Cloudflareで引き続き設定を行います。ここでは、ドメインへのアクセス、コンテンツのキャッシュ・圧縮設定ができます。利用に応じた設定を行ってください。
Cloudflare-NSの変更チェック
次にNSレコードのチェックをします。既にNSの変更が検知できている場合は、以下のような表示になります。
まだ、検知できていない場合は以下のような表示になります。ドメインの設定がネットワーク全体に浸透するまでは24~48時間程かかります。Cloudflareでチェックしても変更されていなかった場合は、少し時間をおいてください。ちなみに、Cloudflareで正常にNSが変更されていることを検知すると、アカウント登録時に設定したメールアドレスに通知がきます。
3. ソーン編集用APIアクセスキーを作成
legoのライブラリを利用するために必要な、CloudflareのDNSゾーン情報APIアクセスキーを作成します。キーは2種類作成します。
ゾーン情報の【DNS編集キー】と【ゾーン編集キー】です。Cloudflareのアカウント設定のAPIトークンから作成することができます。
まず、APIアクセスキーを作成する前に、画面下部にある「Global Api key」も取得しておきましょう。4.のdocker-compose.ymlに記述する必要があるためです。
アクセスキーを作成する際に、いくつかテンプレートが用意されています。今回は【ゾーンDNSを編集する】というテンプレートを編集して利用します。テンプレートを利用せずに0から作成することもできますが、慣れてから使うか、似たテンプレートを変更したほうが無難そうです。
1つのトークンに対して、複数の権限を付与することができますが、トークンが増えてくると管理がしづらくなるので、1トークン1権限で運用することとします。アクセス許可に以下を、それぞれ設定して2つのトークンを作成します。
- 1つ目のトークン
→ ゾーン:DNS:編集- 2つ目のトークン
→ ゾーン:ゾーン:編集- 2つの共通設定(ゾーンリソース)
→ 包含:特定のゾーン:ワイルドカード証明書を発行したいドメイントークン作成を進めると、以下のような画面が表示されます。このときに表示されるトークンをメモしてください。ここで表示されたトークンは、画面にもあるように再表示されません。そのため、必ずメモするようにしてください。メモし忘れたら、APIトークンを削除して、再作成してください。
4. SSL証明書の自動更新スクリプトの作成
会社の社内サービスが動いているDockerでは、以下のような運用がされています。
- 平日(月〜金)は昼夜問わず常時起動
- 休日(土日)に自動シャットダウン
- 月曜にサービスを立ち上げる
このことから、サービスを立ち上げるときにSSL証明書の更新処理を走るようにしておけば、最低週に1回は確認することになり、更新忘れによる証明書失効を防ぐことが出来ると考えました。サービス自体がDockerで運用されているため、SSL更新処理もDocker化して、Serviceとして登録する方向にしました。
lego(https://go-acme.github.io/lego/)を使ったSSL証明書更新用Dockerは以下のように設定しました。
docker-compose.ymlservices: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos run volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてくださいdocker-compose.yml を作成して、docker-composeを実行します。
$ docker-compose up実行が終わると、以下のようなログが流れ、
/opt/cert
配下に証明書本体が格納されているディレクトリと、更新に必要なアカウント情報が含まれているディレクトリが生成されます。❯ docker-compose up Recreating certbot-cloudflare_certbot-lego_1 ... done Attaching to certbot-cloudflare_certbot-lego_1 certbot-lego_1 | 2020/11/28 06:44:01 [INFO] acme: Registering account for [Cloudflareに登録したメールアドレス] certbot-lego_1 | !!!! HEADS UP !!!! certbot-lego_1 | certbot-lego_1 | Your account credentials have been saved in your Let's Encrypt certbot-lego_1 | configuration directory at "/lego/accounts". certbot-lego_1 | certbot-lego_1 | You should make a secure backup of this folder now. This certbot-lego_1 | configuration directory will also contain certificates and certbot-lego_1 | private keys obtained from Let's Encrypt so making regular certbot-lego_1 | backups of this folder is ideal. certbot-lego_1 | 2020/11/28 06:44:01 [INFO] [*.choipre.com, choipre.com] acme: Obtaining bundled SAN certificate certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315819 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315820 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] acme: use dns-01 solver certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: tls-alpn-01 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: http-01 (省略) certbot-lego_1 | 2020/11/28 06:44:11 [INFO] [*.choipre.com, choipre.com] acme: Validations succeeded; requesting certificates certbot-lego_1 | 2020/11/28 06:44:12 [INFO] [*.choipre.com] Server responded with a certificate. certbot-cloudflare_certbot-lego_1 exited with code 0drwxr-xr-x - nomunomu 28 11 15:43 └── opt drwxr-xr-x - nomunomu 28 11 15:44 └── cert drwx------ - nomunomu 28 11 15:43 ├── accounts drwx------ - nomunomu 28 11 15:43 │ └── acme-v02.api.letsencrypt.org drwx------ - nomunomu 28 11 15:44 │ └── xxxxxxxxxxx@gmail.com .rw------- 225 nomunomu 28 11 15:44 │ ├── account.json drwx------ - nomunomu 28 11 15:43 │ └── keys .rw-r--r-- 227 nomunomu 28 11 15:43 │ └── xxxxxxxxxx@gmail.com.key drwx------ - nomunomu 28 11 15:44 └── certificates .rw------- 3.3k nomunomu 28 11 15:44 ├── _.choipre.com.crt .rw------- 1.6k nomunomu 28 11 15:44 ├── _.choipre.com.issuer.crt .rw------- 234 nomunomu 28 11 15:44 ├── _.choipre.com.json .rw------- 227 nomunomu 28 11 15:44 └── _.choipre.com.keyこの生成されたフォルダで、accountsフォルダは今後証明書を更新していくなかで必要になるフォルダです。証明書類はcertificatesに保管されています。
「_.choipre.com.crt」がchoipre.comのワイルドカード証明書になります。一度、証明書発行を実行したので、今後は更新という処理を行う設定にしておく必要があります。そのため、docker-compose.ymlを以下のように変更します。
services: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos renew --days 30 volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてください変更点は、
run
からrenew
コマンドに変更することです。パラメーターとして--days
を指定することで指定した日数を切ってから更新させることができます。この、docker-composeの実行をcronなどに設定することで自動更新を行えるようになります。
5. ワイルドカードをnginxに適用する
4.で生成した証明書をNginxに適用していきます。証明書類は/opt/cert配下にあるものとします。Nginxの設定ファイルに以下の記述を追加します。
追記場所はNginxの設定ファイルの使用したいServer設定の中です。デフォルト構成を利用している人はserver{ ... }
の中に記述します。ssl_certificate /opt/cert/_.choipre.com.crt; ssl_certificate_key /opt/cert/_.choipre.com.key;記述ができたら、Nginxのプロセスを再起動します。Nginxのプロセスを再起動したら、対象のアドレスに対してhttpsアクセスをすると証明書が適用されていることが分かります。
まとめ
以上で、自動更新可能なワイルドカード証明書発行の実装が終わりました。
初期設定は大変ですが、今後はあらゆるサブドメインに対してSSL通信を行うことができます。これでChromeでhttpコンテンツが閲覧できなくなっても、安心ですね。生産性を向上してHappy Lifeを!!
- 投稿日:2020-11-29T12:30:49+09:00
Cloudflare + docker-composeで自動更新可能ワイルドカード証明書を発行して社内サービスをSSL化してみた
この記事は 生産性向上のための環境整備2020 【PR】 Lenovo Advent Calendar 2020 の3日目の記事です。
2日目の記事:腰痛のためのリマインダー機能 by @ryu3
4日目の記事:エンジニアのための目を休ませる最高の環境 @newt0Chromeでhttpサイトが見れなくなる??
Chromeの開発元であるGoogleは以下のような声明を出しました。
(引用元: https://security.googleblog.com/2019/10/no-more-mixed-messages-about-https_3.html)Today we’re announcing that Chrome will gradually start ensuring that https:// pages can only load secure https:// subresources. In a series of steps outlined below, we’ll start blocking mixed content (insecure http:// subresources on https:// pages) by default. This change will improve user privacy and security on the web, and present a clearer browser security UX to users.
本日、Chrome では、https:// ページが安全な https:// サブリソースのみを読み込むことができるようにすることを段階的に開始することを発表しました。以下に概説する一連の手順で、混合コンテンツ ( https:// ページの安全でない http:// サブリソース) をデフォルトでブロックするようになります。この変更により、ウェブ上でのユーザーのプライバシーとセキュリティが改善され、より明確なブラウザセキュリティUXをユーザーに提示することができます。
混合コンテンツ
混合コンテンツとは、https内に存在するhttpなコンテンツのことを指します。
つまり「https://xxxxxxxxx.com/」というセキュアなサイト内で「http://yyyyyyyyyyy.com/image/test.png」のようなセキュアでないコンテンツを呼び出している状態を意味します。つまり、httpなサイトはChromeで閲覧できなくなる可能性があるということです。
さらにこの問題が顕著なのは、日本におけるChromeの利用率が高いという点です。
(参照元: https://lab.syncer.jp/Statistic/Browser/2019/10/)・ デスクトップのシェア:66.14%(1位) ・ モバイルのシェア:26.46%(2位) ・ タブレットのシェア:36.56%(2位)社内だけのサービス(退勤管理やソース管理など)だからといって、セキュア化していないとアクセスできない。なんてことにならないように社内のネットワーク整備をすることにしました。
では、社会人1年目、新卒入社の筆者が社内ネットワーク整備に奮闘した一部始終をどうぞ!!
環境
- CentOS 7
→ 社内サービスがDocker on CentOS7で動いてた- Let's Encrypt
→ 無料で使えるSSL証明書。90日で期限が切れるため更新が必須- Cloudflare
→ ワイルドカード証明書を発行するのにDNSレコードを変更する必要があるため、無料で使えるCloudflareを採用。(このためだけにNSを変更したといっても過言ではない)- lego(https://go-acme.github.io/lego/)
→ Let's Encryptの環境がさくっと作れるDocker環境。大体のDNS Providerに対応してて、それぞれの設定方法や実行方法が書いてあってありがたい。 (対応してるDNS Provider一覧はこちら)改修フロー
https化へのざっくりとしたフローはこちらです。
- 社内サービスへのアクセスをサブドメインで行えるようにする
- ドメインのネームサーバー(NS)をCloudflareに変更
- Cloudflareでソーン編集用APIアクセスキーを作成
- 社内サービスコンテナ内で自動更新スクリプト等の作成
- Nginxなどに証明書を食わせる
今回は検証用の個人的なドメイン(choipre.com)(Google Domains)を使って解説します。
ドメイン取ったけど、個人サービスが完成していないので、何しても大丈夫だし。!! 注意 !!
設定を間違えるとサイトにアクセスできなくなったりする可能性があります。必ず変更点(Diff)などはメモするようにしておいた方が、万が一のためです。バックアップなどを取りつつ作業を進めることをおすすめします。1. 社内サービスへのアクセスをサブドメインで行えるようにする
これまで、社内サービスにはIPアドレスを使ってアクセスしていました。そのためhttps化できず、httpな状態で運用していました。まずは、社内サービスへのアクセスをサブドメインでアクセスできるようにするため、社内DNSを整備します。ドメインは、会社HPなどで元々利用しているものを利用しました。その内容は別記事として割愛します。
2. ドメインのNSをCloudflareに変更
なぜCloudflareに変更したかというと、CloudflareではAPIを使ってドメインのゾーン情報(A, AAAA, TXTなどのDNSレコード情報)を書き換えることができます。
(参考: https://api.cloudflare.com/#zone-subscription-zone-subscription-details)この仕組みを利用して、スクリプト上でワイルドカードのSSL証明書を発行するのに必要なレコード内容を自動で書き込みたかったからです。
(証明書更新する度に手動でDNSレコードに追記したり、削除したりするのって面倒だし、ネットワークの知識がない人が更新しないといけないってなったときに、このコマンド一発叩けばいいよ!の方がいいよね?)Cloudflareにドメインを登録
Cloudflareのアカウントを持っていない人はアカウント作成してください。
アカウント作成後、トップ画面に 【サイトを追加する】 を押します。
(※ 画像は既に登録済みのドメインがあるため、Cloudflareの管理下にあるドメイン一覧がありますが、初期登録後の人は何も表示されていません。)
プラン選択画面が表示されるので 【Freeプラン】 を選択します。
(Freeプランでここまで出来るってCloudflare様様...)
Cloudflareに既存DNSレコードを移植
ドメインの登録が完了すると、現在設定されているDNSレコードを読み取って、Cloudflareに書き込み準備をしてくれます。このときにDNSレコードを修正することもできますが、必要がない人はそのまま 【続行】 します。
ただし、AレコードとMXレコードが同一の場合、AレコードをCloudflareのプロキシから外す必要があります。プロキシから外してDNS解決のみにしないとメールサーバーが正常に動作しないためです。
(参考: Cloudflareの使用時にメールが配信不能になる - メール関連のDNSレコード)
CloudflareのNSに変更する
Cloudflareに取り込むDNSレコードの設定が終わったら、ドメインのNSをCloudflareに変更するように促されます。
各ドメインの管理画面からドメインのNSを変更します。今回の検証用ドメインはGoogle Domainsで取得しているため、Google Domainsの設定画面から変更します。
ドメインのNS変更が終わったら、Cloudflareで引き続き設定を行います。ここでは、ドメインへのアクセス、コンテンツのキャッシュ・圧縮設定ができます。利用に応じた設定を行ってください。
Cloudflare-NSの変更チェック
次にNSレコードのチェックをします。既にNSの変更が検知できている場合は、以下のような表示になります。
まだ、検知できていない場合は以下のような表示になります。ドメインの設定がネットワーク全体に浸透するまでは24~48時間程かかります。Cloudflareでチェックしても変更されていなかった場合は、少し時間をおいてください。ちなみに、Cloudflareで正常にNSが変更されていることを検知すると、アカウント登録時に設定したメールアドレスに通知がきます。
3. ソーン編集用APIアクセスキーを作成
legoのライブラリを利用するために必要な、CloudflareのDNSゾーン情報APIアクセスキーを作成します。キーは2種類作成します。
ゾーン情報の【DNS編集キー】と【ゾーン編集キー】です。Cloudflareのアカウント設定のAPIトークンから作成することができます。
まず、APIアクセスキーを作成する前に、画面下部にある「Global Api key」も取得しておきましょう。4.のdocker-compose.ymlに記述する必要があるためです。
アクセスキーを作成する際に、いくつかテンプレートが用意されています。今回は【ゾーンDNSを編集する】というテンプレートを編集して利用します。テンプレートを利用せずに0から作成することもできますが、慣れてから使うか、似たテンプレートを変更したほうが無難そうです。
1つのトークンに対して、複数の権限を付与することができますが、トークンが増えてくると管理がしづらくなるので、1トークン1権限で運用することとします。アクセス許可に以下を、それぞれ設定して2つのトークンを作成します。
- 1つ目のトークン
→ ゾーン:DNS:編集- 2つ目のトークン
→ ゾーン:ゾーン:編集- 2つの共通設定(ゾーンリソース)
→ 包含:特定のゾーン:ワイルドカード証明書を発行したいドメイントークン作成を進めると、以下のような画面が表示されます。このときに表示されるトークンをメモしてください。ここで表示されたトークンは、画面にもあるように再表示されません。そのため、必ずメモするようにしてください。メモし忘れたら、APIトークンを削除して、再作成してください。
4. SSL証明書の自動更新スクリプトの作成
会社の社内サービスが動いているDockerでは、以下のような運用がされています。
- 平日(月〜金)は昼夜問わず常時起動
- 休日(土日)に自動シャットダウン
- 月曜にサービスを立ち上げる
このことから、サービスを立ち上げるときにSSL証明書の更新処理を走るようにしておけば、最低週に1回は確認することになり、更新忘れによる証明書失効を防ぐことが出来ると考えました。サービス自体がDockerで運用されているため、SSL更新処理もDocker化して、Serviceとして登録する方向にしました。
lego(https://go-acme.github.io/lego/)を使ったSSL証明書更新用Dockerは以下のように設定しました。
docker-compose.ymlservices: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos run volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてくださいdocker-compose.yml を作成して、docker-composeを実行します。
$ docker-compose up実行が終わると、以下のようなログが流れ、
/opt/cert
配下に証明書本体が格納されているディレクトリと、更新に必要なアカウント情報が含まれているディレクトリが生成されます。❯ docker-compose up Recreating certbot-cloudflare_certbot-lego_1 ... done Attaching to certbot-cloudflare_certbot-lego_1 certbot-lego_1 | 2020/11/28 06:44:01 [INFO] acme: Registering account for [Cloudflareに登録したメールアドレス] certbot-lego_1 | !!!! HEADS UP !!!! certbot-lego_1 | certbot-lego_1 | Your account credentials have been saved in your Let's Encrypt certbot-lego_1 | configuration directory at "/lego/accounts". certbot-lego_1 | certbot-lego_1 | You should make a secure backup of this folder now. This certbot-lego_1 | configuration directory will also contain certificates and certbot-lego_1 | private keys obtained from Let's Encrypt so making regular certbot-lego_1 | backups of this folder is ideal. certbot-lego_1 | 2020/11/28 06:44:01 [INFO] [*.choipre.com, choipre.com] acme: Obtaining bundled SAN certificate certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315819 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315820 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] acme: use dns-01 solver certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: tls-alpn-01 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: http-01 (省略) certbot-lego_1 | 2020/11/28 06:44:11 [INFO] [*.choipre.com, choipre.com] acme: Validations succeeded; requesting certificates certbot-lego_1 | 2020/11/28 06:44:12 [INFO] [*.choipre.com] Server responded with a certificate. certbot-cloudflare_certbot-lego_1 exited with code 0drwxr-xr-x - nomunomu 28 11 15:43 └── opt drwxr-xr-x - nomunomu 28 11 15:44 └── cert drwx------ - nomunomu 28 11 15:43 ├── accounts drwx------ - nomunomu 28 11 15:43 │ └── acme-v02.api.letsencrypt.org drwx------ - nomunomu 28 11 15:44 │ └── xxxxxxxxxxx@gmail.com .rw------- 225 nomunomu 28 11 15:44 │ ├── account.json drwx------ - nomunomu 28 11 15:43 │ └── keys .rw-r--r-- 227 nomunomu 28 11 15:43 │ └── xxxxxxxxxx@gmail.com.key drwx------ - nomunomu 28 11 15:44 └── certificates .rw------- 3.3k nomunomu 28 11 15:44 ├── _.choipre.com.crt .rw------- 1.6k nomunomu 28 11 15:44 ├── _.choipre.com.issuer.crt .rw------- 234 nomunomu 28 11 15:44 ├── _.choipre.com.json .rw------- 227 nomunomu 28 11 15:44 └── _.choipre.com.keyこの生成されたフォルダで、accountsフォルダは今後証明書を更新していくなかで必要になるフォルダです。証明書類はcertificatesに保管されています。
「_.choipre.com.crt」がchoipre.comのワイルドカード証明書になります。一度、証明書発行を実行したので、今後は更新という処理を行う設定にしておく必要があります。そのため、docker-compose.ymlを以下のように変更します。
services: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos renew --days 30 volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてください変更点は、
run
からrenew
コマンドに変更することです。パラメーターとして--days
を指定することで指定した日数を切ってから更新させることができます。この、docker-composeの実行をcronなどに設定することで自動更新を行えるようになります。
5. ワイルドカードをnginxに適用する
4.で生成した証明書をNginxに適用していきます。証明書類は/opt/cert配下にあるものとします。Nginxの設定ファイルに以下の記述を追加します。
追記場所はNginxの設定ファイルの使用したいServer設定の中です。デフォルト構成を利用している人はserver{ ... }
の中に記述します。ssl_certificate /opt/cert/_.choipre.com.crt; ssl_certificate_key /opt/cert/_.choipre.com.key;記述ができたら、Nginxのプロセスを再起動します。Nginxのプロセスを再起動したら、対象のアドレスに対してhttpsアクセスをすると証明書が適用されていることが分かります。
まとめ
以上で、自動更新可能なワイルドカード証明書発行の実装が終わりました。
初期設定は大変ですが、今後はあらゆるサブドメインに対してSSL通信を行うことができます。これでChromeでhttpコンテンツが閲覧できなくなっても、安心ですね。生産性を向上してHappy Lifeを!!
- 投稿日:2020-11-29T11:55:25+09:00
[Fargate 入門] ECS(Fargate)でrakeタスクを実行するまで
Fargateで単純なrakeタスクを実行するまでの手順。
タスク定義やコンテナの設定などがややこしかったため備忘録として。準備
実行するrakeタスクとコンテナイメージを用意します。
rakeタスクの作成
今回はrakeタスク実行が確認できれば良いので単純なタスクを用意。
namespace :ecs_task do task :hoge do puts "task started" end endコンテナイメージの用意
以下のようなDockerfileを作成し、rakeタスクが実行できる環境を用意します。
DockerfileFROM ruby:2.5.3 # 環境変数 ENV LANG C.UTF-8 ENV APP_ROOT /app # ソースをコンテナに転送 ADD ./ $APP_ROOT # コンテナ内の作業ディレクトリの設定 WORKDIR $APP_ROOT # gemのインストール RUN gem update bundler RUN bundle installコンテナイメージをECRへプッシュする
Fargateでタスクを実行するためにDockerfileからイメージを作成してECRにプッシュします。
(Docker Hubでも良いですが今回はECRを利用)マネジメントコンソールからリポジトリを作成しましょう。
下記のようにリポジトリが作成されたらOKです。
プッシュコマンドの表示を押すと、ECRへイメージをプッシュする手順が表示されるので、手順にしたがってプッシュします。
プッシュ後、下記のようにイメージが存在すればOKです。
準備は完了したので、ECSでクラスターとタスク定義を作成していきましょう。
ECS
マネジメントコンソール上でクラスターとタスク定義を作成していきます。
クラスターの作成
ECS > クラスターからクラスターを作成します。
今回はFargateを利用するので、ネットワーキングのみ(AWS Fargateを使用)を選択。
クラスターの名前を入れて作成。
今回は既存のVPCを利用するのでVPCは作成しませんでした。
これでクラスター作成は完了しました。タスク定義の作成
次にクラスターで実行させるタスクを作成していきます。
起動タイプの互換性の選択で、こちらもFargateを選択します。タスクとコンテナの設定
タスクロール
タスクを実行するコンテナに付与するIAMロールです。タスクでS3やRDSなどAWSサービスにアクセスする必要がある場合は、必要な権限を持ったロールを設定します。
今回は不要なのでスキップ。タスクの実行IAMロール
タスクを実行(開始)するために必要なロールです。
説明にもありますが、コンテナイメージをECRからプルしたり、コンテナのログをCloudWatch Logsに吐き出すための権限を持ったロールが必要になります。
初回は新しいロールの作成
で自動的に必要なロールを作成してくれるのでこのままでOK。タスクサイズ
タスクの実行に使用されるメモリとCPUを設定します。(Fargateでは必須)
ひとまず最小限のメモリとCPUを設定しました。
コンテナの設定
タスク実行に必要なコンテナの設定をします。
基本設定
スタンダード(基本設定) コンテナ名 コンテナの名前 イメージ コンテナのURI(ECRからコピーできます) プライベートレジストリの認証 プライベートのリポジトリからイメージをプルする場合に必要(ECRを利用する場合は不要) メモリ制限(MiB) コンテナに対するメモリの制限ですが、Fargateではタスクに対してサイズを設定しているので、コンテナで制限をかける意味はよくわかっていません。 ポートマッピング コンテナのポートとホストインスタンスのポートを紐づける場合に設定します。
今回は単純なrake実行のみなので使用しません。環境
コンテナ環境で実行したいコマンドと作業ディレクトリを以下のように指定。
その他
ヘルスチェックやネットワークの設定などがありますが今回は使用しないので入力する必要はありません。
以上でタスク定義の設定は終了です。
タスクの実行
さっそくタスクを実行していきましょう。
タスク実行時の設定を入力していきます。
起動タイプはFARGATE、タスクを実行するVPCやサブネットなどを入力し、タスクの実行をクリック。
ログの確認
ちゃんとタスクが実行されているかログを確認してみましょう。
タスクの実行ログはデフォルトではCloudWatch Logsに吐き出されます。ロググループに
/ecs/タスク名
が作成されていますのでクリック。
タスクが実行されたことがわかりました。
所感
初めてECSを触ったということもありますが、色々設定することが多く初めは手間取りました。
タスク定義(コンテナ周り)など、まだまだ今回使っていない設定項目は多数あるので、今後調べていきます。
また今回は1コンテナ、単純なrakeタスクの実行しかしていないので、複数コンテナの連携(フロント、バックエンド、DB)などをECSで行ってみようと思います。