こんにちは。最近になって、約2ヶ月取り組んでいるダイエットの効果がでてきて、俄然やる気が出てきているkumicoです。この記事は、ブログのデプロイをAnsibleで自動化した話について書いています。

このブログについて

このブログは、devocのブログを支える技術 with Caddyという記事で紹介したように、VPS上にDockerを立てて、ブログのページと配信サーバをコンテナとして動かしています。

新たに記事を投稿するときは、以下のような手順を行なっていました。

  1. 手元のPCで記事を執筆する
  2. Hugoを使ってビルドする
  3. ビルドしたファイルごとGitHubにプッシュする
  4. GitHub Actionsを使って,Dockerイメージのビルドを行う(このときブログページをコンテナにコピーしている)
  5. ビルドしたイメージをGitHub Container Registryにプッシュする
  6. VPSにSSHして最新のコンテナイメージをpullしてコンテナを起動すれば,投稿完了 <— デプロイするたびに、VPSにsshして最新のコンテナイメージをプルして、動いてるコンテナをkillしてからプルしてきたイメージを使ってコンテナを立て直さないといけない。

今回は6のところをGitHub ActionsからAnsibleを使うことで、自動化しました。

ワークフロー

以下のようなワークフローを作成しました。

  deploy:
    needs: push
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Install Ansible
        run: sudo apt install -y ansible //ランナーにAnsibleをインストール

      - name: setup ssh config
        env:
          SSH_AUTH_SOCK: /tmp/ssh_agent.sock
        run: |
          mkdir -p ~/.ssh
          ssh-keyscan "ssh先のドメイン名" >> ~/.ssh/known_hosts //これをいれとかないと、インタラクティブな処理が入る
          echo "${{ secrets.LIGHTSAIL_PRIVATE }}" > ~/.ssh/id_rsa //リポジトリに登録した秘密鍵をActionsのランナーに登録
          chmod 600 ~/.ssh/id_rsa //秘密鍵の権限を適切に設定
          eval $(ssh-agent -s)
          ssh-add ~/.ssh/id_rsa
          ansible-playbook -i ./inventory ./playbook.yml // playbookを実行
        working-directory: ./ansible

playbookの中身は、ssh先で今まで手動で行っていた、

  1. コンテナのkill
  2. コンテナの削除
  3. 最新のイメージのプル
  4. プルしたイメージを用いてコンテナを立ち上げる

といった作業を記述しています。

  • ansibleディレクトリの中身
ansible/
├── ansible.cfg
├── inventory
└── playbook.yml
  • 各ファイルの中身
//ansible.cfg

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
//inventory
[hoge]
example.com //your domain

[hoge:vars]
ansible_root=22
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/id_rsa
//playbook.yml
- hosts: hoge
  tasks:
    - name: Kill container process
      command: sudo docker kill containername
    - name: Remove container
      command: sudo docker rm containername
    - name: Pull container image
      command: sudo docker pull container-registry
    - name: Run container
      command: sudo docker run --name containername
    - name: Prune docker image
      command: sudo docker image prune -f

自分は、特定のブランチにマージされた時にCIが走るようになっているので、pushしてマージするだけで、イメージのビルドからデプロイ(手作業を自動化しただけなので、デプロイと言えるかどうか)まで自動化できた。

次に整備すること 

現状、デプロイがかなり楽になっているが、記事を作成する作業は、Hugoが入ってる端末でしか作業できないのでDockerfileさえあれば開発できるようにはなってない。Hugoでのページビルドの作業もコンテナないで行い、生成されたページだけをコンテナに乗せるようにすれば、Gitで管理するコードがページの元になるMarkdownや画像のような静的ファイルのみでよくなり、無駄なファイルをPushしなくて済むようになる。