【后端开发一体化解决方案】利用Docker、Rails、Circle CI和Terraform进行基础架构的代码环境搭建及自动容器部署至ECS【上篇】

只要有流行的技术,我们就想要使用。

大家早上好。又到了一年一度的感觉如雪花般飞舞的季节。大家过得如何呢?是否和现实环境相处融洽?我与现实环境的关系正在日益紧张。没关系,毕竟人生始终都是实际的考验(?)。

现在,在工程师们之间的以工程师为目标的工程师论中,已经不再

    • (主にサーバーサイドの)アプリをDockerを使って環境構築して

terraformでインフラの構成をコード化して
(Kubernetesなどのコンテナオーケストレーションツールを用いて)なるべく開発環境との差異が無いままコンテナデプロイをして

CircleCIでテストからデプロイまで自動化

作为服务器端工程师,经常会看到类似的意见,说如果不知道这些方面的要求,就很难继续工作下去了。

观点将在另一个时机讨论。(假设如此),对于初学者有意向成为服务器端工程师的同学们来说,以下这些

    • Docker

 

    • CircleCI

 

    • Terraform

 

    コンテナデプロイ(今回はECS)

我认为以教程的形式迅速学习和整理自己的理解可能是最快的方式!你觉得呢?换句话说,通过这篇文章,你能接触到目前流行的服务器端技术的各个方面!我对它的广度感到有点后悔。

好吧,那我就写吧!可能会再次变得有点长…

过去的长篇文章
【针对初学者】Rails “关联” 教程过于详细【无论如何】【完美理解】
【针对初学者】使用Heroku确保可以成功部署Rails应用程序的方法【决定版】

明天(12/5)单独演唱会,如果方便的话请来参加
音乐视频
预约请点击这里

目录

阅读本文的前提条件

    • gitとgithubを使った事がある

 

    • Dockerをなんとなく理解している

 

    • Railsも触ったことある(触ったことなくてもできるかも)

 

    AWSのコンソールでEC2やVPCを立てた事がある

当然,我也非常鼓励其他人尝试挑战。理解可以事后补救。编程是靠实践来记忆的。

能掌握的技能或能力

使用Docker可以构建Rails应用程序,并在推送时通过CircleCI自动运行,并能够自动部署到之前通过Terraform构建的AWS环境(ECS)中!

我希望你重视一件事

    • DBはsqliteです。RDSとつないでません。

 

    • Webサーバもpumaで兼用してます。nginxなどのWebサーバーとつないでません

 

    =>これらはまた次回やろうと思います!

##我的环境

    • Ruby 2.6.3

 

    • Rails 6.0.1

 

    • Docker 19.03.4

 

    • Git 2.14.1

 

    Terraform 0.12.8

让我们全面了解这个问题

将各种工具和服务相互连接起来,需要非常重视对整体情况的把握。
首先,让我们确认整体流程。按照时间顺序列举如下:

应用程序自动部署到容器的流程

0. 使用Terraform定义AWS上的资源
1. 将Rails应用推送到Github
2. 在CircleCI上开始CI
3. 在CI中构建Docker镜像
4. 将Docker镜像推送到ECR
5. 更新ECS的任务定义
6. 在CI中进行数据迁移
7. 应用程序部署完成!

用图像来表示的话,下面是:

image.png

大致上解释每个工具的作用

基于云计算的基础设施即代码工具

基础设施定义工具。它可以将云上的资源生成并操作为定义文件的状态。将在屏幕上点点点操作的基础设施转化为代码。

####轨道交通系统

我想要部署的应用本身。

####Github

GitHub 是一个面向开源及私有软件项目的托管平台,能够帮助开发者进行版本控制、协作和代码管理。

版本控制工具。
就像是将应用程序与CircleCI连接起来的中枢角色。

CircleCI
CI with a circular structure

可以通过自动执行的服务来进行构建/测试/部署等操作。
利用这项服务可以自动化各种繁琐的任务。

Docker是一种容器化平台。

一个包含了所有运行应用程序所需的虚拟化平台。因为Rails可以在这个平台上运行,所以我想直接将包含Rails应用程序的Docker容器部署到生产环境中。

以下翻译仅提供一种中文版本:

ECR

可以把容器映像存储在私有环境的服务中。
我想把包含Rails应用环境的Docker容器映像放在这里。

Elastic Compute Service(ECS)的原文意思是弹性计算服务。

AWS是一项能够简化在EC2上通过Docker容器进行处理和启动服务的服务。由于在EC2上的操作都由AWS负责,因此部署应该很容易(虽然事实并非完全如此)。

没问题!非常丰富!
好的,请放心,我会按照通常的顺序进行解释。

我们首先使用Docker来创建一个能够运行Rails应用的环境吧!

通过使用Docker来构建Rails环境。

暫時在本地環境中先建立一次。
由於想要將terraform和rails應用程序放在同一個目錄下,我們創建一個名為terraform_ecs_deploy的目錄(請小心不要與github存儲庫混淆!)

$ mkdir terraform_ecs_deploy
$ cd terraform_ecs_deploy
$ rails new terraform_ecs_app --skip-javascript # webpackerは今回いらないです
$ cd terraform_ecs_app
$ rails db:migrate

现在,在这个时间点上我们要将Rails应用程序进行Docker化。
我们要创建一个Dockerfile,并获取官方的Ruby镜像,然后写入以下内容。
(请谅解我们这次只准备了一个简单的Dockerfile。)

Docker的安装在这里。

# 公式のイメージから取得
FROM ruby:2.6.3

# Dockerfile内部で使える変数として定義
ARG RAILS_ENV
ARG RAILS_MASTER_KEY

# コンテナ内のルートとする変数を/appと定義
ENV APP_ROOT /app

# 環境変数化
ENV RAILS_ENV ${RAILS_ENV}
ENV RAILS_MASTER_KEY ${RAILS_MASTER_KEY}

# コンテナ内のルートとする。
WORKDIR $APP_ROOT

# ローカルのGemfile, Gemfile.lockをコンテナ内のルートへコピー
ADD Gemfile $APP_ROOT
ADD Gemfile.lock $APP_ROOT

# bundle install実行。
# (バージョンのエラーが出る為、一応bundler 2.0.2を指定)
RUN \
    gem install bundler:2.0.2 && \ 
    bundle install && \
    rm -rf ~/.gem

# バンドルインストールが終わってから他のファイルもコンテナ内へコピー
ADD . $APP_ROOT

# 本番環境の場合プロダクション
RUN if ["${RAILS_ENV}" = "production"]; then bundle exec rails assets:precompile; else export RAILS_ENV=development; fi

# ポート3000番を公開
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

那么,根据这个Dockerfile构建Docker容器,并尝试启动rails。

$ docker build -t terraform_ecs_app:latest . # -tでタグを指定
$ docker run -it -p 3000:3000 terraform_ecs_app:latest # -it

在运行docker时,选项如下列所示。

-i,–interactive:与容器的STDIN连接
-t,–tty:分配伪终端

如果是这样的话,那就可以了。

image.png

当您访问 http://localhost:3000,应该会出现熟悉的界面。

image.png

※注意!如果 docker run -it -p 3000:3000 terraform_ecs_app:latest 不能运行,请留意。

在这里的话 (Moshi koko de)

docker: you are not authorized to perform this operation: server returned 401.
See 'docker run --help'.

如果出现此类错误,请在终端中输入以下命令设置环境变量。

export DOCKER_CONTENT_TRUST=0

通过这样做,可以跳过对Docker镜像是否被篡改的完整性检查,理论上应该可以执行上述命令。

关于Docker内容信任(DCT)

Rails的详细设置

那么,这次的重点不是关于Rails的讨论,所以功能上只需要简单的即可。因此,

    • 表示用のトップ画面

ALB(Application Load Balancer)のHealthCheck用に、jsonでstatus: okが帰ってくるURL

我们只需要实现其中两个。(当然后面也会提到ALB和健康检查。)

$ rails g controller top index 
$ rails g controller health_check

由于顶层控制器应该已经自动生成了动作和视图,因此只需更改health_check控制器。

class HealthCheckController < ApplicationController
  # ALBにステータスokを返す為のアクション
  def index
    render json: '{ "status": "ok" }'
  end
end

我也会更改路由器设置。

Rails.application.routes.draw do
  root to: 'top#index'
  resources :health_check, only: [:index]
end

只要按如下方式显示就可以。

image.png
image.png

另外,为了避免在生产环境中出现无法创建tmp/pids和tmp/sockets的情况,请在.gitignore中添加以下内容作为一种预防措施。

# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
/db/*.sqlite3-*

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# ===============追加================
!/tmp/pids
!/tmp/sockets
# =============ここまで===============
# Ignore uploaded files in development.
/storage/*
!/storage/.keep

/public/assets
.byebug_history

# Ignore master key for decrypting credentials and more.
/config/master.key

我们已经实现了最低限度的功能,现在让我们将代码推送到GitHub上。

将Rails应用程序推送到GitHub上。

这次将省略对Git和GitHub的解释。

Git的安装
GitHub的使用方法

请确保当前目录是一个Rails应用程序,然后执行以下命令。
(我这里将仓库名称设置为terraform_ecs_app。)

$ git init
$ git commit -m "initial commit"
$ git remote add origin リポジトリのURL
$ git push origin master

如果GitHub上的存储库如下所示,那就可以了。

image.png

现在,我们开始进行CircleCI的CI设置吧!

在CircleCI上进行CI设置

CircleCI是一种基于Saas的CI/CD服务,它可以自动化构建、测试和部署这三个基本任务,这也是CI/CD的基础。

我們這次想要利用這個來進行測試和部署(推送至ECR)的自動化。

请参考以下链接了解关于CircleCI的特点和价格。虽然现在有点晚,但我已经开始入门CircleCI了,所以我试着把它简单明了地总结起来。

###引入CircleCI

image.png

请点击URL右上方的Login,然后按下Log in with Github进行登录。
这样就会自动与Github相关联,进入CI的设置页面。CircleCI

image.png

按下”Add Projects”之后,您的GitHub仓库会显示出来。从中选择刚刚创建的terraform_ecs_app。然后点击”Set Up Project”。

スクリーンショット_2019-12-04_10_39_28.png

然后,我认为会进入到项目的设置页面。
操作系统是Linux,
编程语言仍然使用Ruby也没有问题。

而且,在下面直接有英语的教程。如果要翻译成中文的话,

创建名为.circleci的文件夹,并添加config.yml文件(文件路径应为.circleci/config.yml)。

将sample.yml的内容输入到config.yml中(请参考以下)。

更新sample.yml以反映项目配置。

将这些更改推送到GitHub。

开始构建!这将在CircleCI中启动项目并侦听Webhook的工作更新。

听说是这样的。实际上,在那座大厦底下,事先有CircleCI为Rails准备的配置文件sample.yml。
按照指示,只需复制粘贴这个文件,在本地环境中创建一个名为.circleci的文件夹,并在其中创建一个名为config.yml的文件,然后将其粘贴到其中即可。

然而,由于使用的Ruby版本不同以及测试框架是rspec,本次请将以下内容修改为使用Rails默认测试框架minitest的版本。

# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
# jobsの中にタスクを定義。一番下のworkflowのjobsのなかで定義したタスクを使う。
jobs:
  # buildという名前のタスク定義
  build:
    docker:
      # specify the version you desire here
      - image: circleci/ruby:2.6.3-node-browsers


      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/postgres:9.4

    working_directory: ~/repo

    # 実際の処理内容
    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-
      # runのたびに実行
      - run:
          name: install dependencies
          command: |
            gem install bundler -v 2.0.2
            bundle install --jobs=4 --retry=3 --path vendor/bundle

      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      # Database setup
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

      # run tests
      - run:
          name: run tests
          command: |
            DISABLE_SPRING=true bundle exec rails test
            

      # collect reports
      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results

如果你完成了这一步骤,请返回之前的CircleCI设置页面,点击右侧的第5个“开始构建”。CircleCI将开始运行。

スクリーンショット_2019-12-04_11_04_15.png

通过这样的方式,以后每次推送时CircleCI将开始执行工作!

顺便提一下,由于改变了routes.rb文件,导致测试失败了,所以请您在推送和构建之前,将对应的测试注释掉,或者将其正确描述(path改为root_path)。

image.png

如果成功,CircleCI的JOBS选项卡将显示为以下内容(绿色的位于最上方)。

image.png

终于来到了这一步,现在让我们开始使用Terraform吧!

准备使用Terraform

安装Terraform
Terraform官方网站
通过使用Terraform,您可以将以前的基础设施流程转化成可用代码。

在中国,您可以使用Homebrew进行安装,但建议使用tfenv作为Terraform的版本管理工具。它易于跟踪版本更新。
首先,让我们安装tfenv自身。

$ brew install tfenv
$ tfenv --version
tfenv 1.0.1

你可以使用list-remote命令来确认可以安装的Terraform版本。在这里,我们选择安装0.12.8版本。

$ tfenv list-remote
.
.
0.12.8
$ tfenv install 0.12.8
$ terraform -v
Terraform v0.12.8

设置IAM用户以便在Terraform中处理AWS。

要使用terraform处理AWS,需要IAM用户的ACCESS KEY、SECRET KEY (以及DEFAULT REGION)。

因为这里无法受Terraform管控,所以请在AWS控制台上创建IAM用户并生成访问密钥和秘钥。

创建IAM用户

如果能够发布,请在终端中将访问密钥和秘密密钥设置为环境变量。

 $ export AWS_ACCESS_KEY_ID=AKIxxxxxxxxx
 $ export AWS_SECRET_ACCESS_KEY=wJalxxxxxxxxxxxxxxxx
 $ export AWS_DEFAULT_REGION=ap-northeast-1

如果关掉电脑或者退出终端,文本会消失,所以请重新输入一遍。

这次我使用了已附加了AdministratorAccess策略的IAM用户的访问密钥,请小心处理,因为这是相当强大的权限。
(千万不要错误地在GitHub等地方公开!)
除了AdministratorAccess策略,其他权限可能不足以执行Terraform操作,如果遇到这种情况,请参考错误消息并分配所需的权限。

现在我们已经准备好开始使用Terraform了!

创建用于Terraform的GitHub存储库。

因为应用程序开发和持续集成以及基础架构的配置是两码事,所以根据理论应该将它们分开存储在不同的代码仓库中。
这次我们将创建一个名为”terraform_ecs”的Github代码仓库。

由于处理秘密情报,请注意将其放入私有库中。

image.png

嗯,关于Terraform的目录结构有很多不同的想法,您可以参考以下链接:
https://dev.classmethod.jp/devops/directory-layout-bestpractice-in-terraform/
https://qiita.com/anfangd/items/1b84f69fa2a4f8a29fbc
https://future-architect.github.io/articles/20190903/

这次为了方便起见,我们将仅在环境中分别创建目录,并将所有的tf文件都放入其中。

terraform_ecs_deploy
├──terraform_ecs_app
└──terraform_ecs
    ├──prod
    └──stg

另外,这次不会进行分阶段环境的构建!因为几乎是在做相同的事情,所以一旦在生产环境中构建完成,马上就能做到。

那么,让我们立即创建一个用于terraform的目录吧。 , yú terraform de ba.)

$ cd .. # railsアプリにいた場合
$ pwd
/Users/matsumotokazuki/Desktop/terraform_ecs_deploy # terraform_ecs_deployにいることを確認。
$ mkdir terraform_ecs
$ mkdir terraform_ecs/prod
$ cd terraform_ecs/prod

如果目录结构像这样,那就没问题了。

terraform_ecs_deploy
├──terraform_ecs_app
└──terraform_ecs
    └──prod # カレントディレクトリ

在将代码推送到GitHub之前,需要将代表Terraform基础架构配置文件的terraform.tfstate以及代表敏感信息的terraform.tfvars从GIT的版本控制中排除掉。(后面也会提到这一点)

$touch .gitignore
/.terraform/*
/terraform.tfvars
/terraform.tfstate

那么,让我们推进吧。

$ cd .. # terraform_ecsディレクトリに移動
$ git init
$ git add -A
$ git commit -m "initial commit"
$ git remote add origin リポジトリ名
$ git push origin master
image.png

前半结束于此

在各项准备工作完成后,我们将暂时停止。现在开始使用Terraform来构建基础设施,还请耐心等待。

我计划选择后半部分。

广告
将在 10 秒后关闭
bannerAds