1.この記事で達成したいこと

  • GitHub Actionsでyqのコンテナイメージを使ってマニフェストを更新したい
    • yqはPythonのパッケージマネージャのpipでも扱うことが出来るけどコンテナイメージで扱うほうが都合がよさそうなのでコンテナイメージでがんばりたい
    • コンテナイメージで扱うというのは、docker runコマンドでyqのイメージをスポットで使う感じ
    • yqの使い方についてはjqのyaml版と思って大丈夫。詳細は以前書いた記事を参考にしてほしい。
    • yqコマンド(jq wrapper for YAML)使い方備忘録
$ docker run --rm -v "$PWD:$PWD" -w="$PWD" \
  --entrypoint yq linuxserver/yq \
  <yqコマンド>

GitHub Actions上でDockerコンテナイメージを扱う方法と注意点

  • やることは addnab/docker-run-action を使うだけ
    • 基本的な使い方はaddnab/docker-run-actionの上記のリンクにサンプルコードを添えて書かれている
  • しかし、docker runコマンドのときのように同アクションを使おうとすると、ホストとコンテナ間でマニフェストが置かれたディレクトリをマウントするところでつまずいた
  • そこで、この記事では特に同アクションを使う際のホストとコンテナ間でディレクトリをマウント方法する方法について、yqのコンテナイメージを使って解説していきたい

2.前提

↓この記事で使うyq
Githubhttps://github.com/kislyuk/yqhttps://github.com/mikefarah/yq
Docker Imagehttps://hub.docker.com/r/linuxserver/yqhttps://hub.docker.com/r/mikefarah/yq

3.環境情報

  • ローカル始めバージョンを書いておく必要があるものはない
  • 使うActionやyqのイメージのバージョンについては後述するWorkflowを参照してほしい

4.この記事で扱うサンプルコード(つまずいたところは解決済)

  • yqのコンテナイメージで更新対象のマニフェスト(manifests/deployment.yml.tmpl)
    • 書き換え箇所はマニフェストのごく一部なので抜粋する
---
apiVersion: apps/v1
kind: Deployment
metadata:
# 略
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sampleapp
  template:
    metadata:
      labels:
        app: sampleapp
    spec:
      affinity:
# 略
      containers:
      - name: sampleapp
        image:  <REGISTRY>/<CONTAINER_IMAGE>:<IMAGE_TAG>
        ports:
        - containerPort: 80
  • yqのコンテナイメージを使うWorkflow(.github/workflows/mod_manifest.yml)
jobs:
  main:
    runs-on: 'ubuntu-20.04'
    env:
      MANIFEST_PATH: 'manifests'

    steps:
      - name: Modify image tag
        uses: addnab/docker-run-action@v3
        with:
          ## yqのイメージを指定
          image: linuxserver/yq:2.13.0
          ## docker runコマンドで渡していたオプションを書く
          ## ">"を使い、適宜改行する
          ## -vオプションの使い方はやや注意なので後述
          options: >
            --rm -v ${{ github.workspace }}/${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }}
            -w=/opt/${{ env.MANIFEST_PATH }}
            --entrypoint yq            
          shell: bash
          run: >
            yq -ry '.spec.template.spec.containers[0].image 
            |="'${{ secrets.REGISTRY }}'/'${{ secrets.CONTAINER_IMAGE }}':'${{ github.sha }}'"'
            /opt/${{ env.MANIFEST_PATH }}/deployment.yml.tmpl > /opt/${{ env.MANIFEST_PATH }}/deployment.yml            

5.addnab/docker-run-actionでディレクトリをマウントする間違ったやり方

  • -vオプションで指定するホスト側のパスを「リポジトリのルートディレクトリからマニフェストの 相対パス 」とする
      - name: Modify image tag
        uses: addnab/docker-run-action@v3
        with:
          ## yqのイメージを指定
          image: linuxserver/yq:2.13.0
          ## docker runコマンドで渡していたオプションを書く
          ## ">"を使い、適宜改行する
          ## -vオプションで指定するホスト側のパスを「リポジトリのルートディレクトリからマニフェストの相対パス」とする
          options: >
            --rm -v ${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }}
            -w=/opt/${{ env.MANIFEST_PATH }}
            --entrypoint yq            
          shell: bash
          run: >
            yq -ry '.spec.template.spec.containers[0].image 
            |="'${{ env.REGISTRY }}'/'${{ env.CONTAINER_IMAGE }}':'${{ github.sha }}'"'
            /opt/${{ env.MANIFEST_PATH }}/deployment.yml.tmpl > /opt/${{ env.MANIFEST_PATH }}/deployment.yml            
  • 実行するとエラーとなってしまう、、
    • yq: error: argument files: can’t open ‘/opt/manifests/deployment.yml.tmpl’: [Errno 2] No such file or directory: ‘/opt/manifests/deployment.yml.tmpl’
  • エラーログ抜粋
Run addnab/docker-run-action@v3
  with:
    image: linuxserver/yq:2.13.0
    options: --rm -v manifests:/opt/manifests -w=/opt/manifests --entrypoint yq
  
    shell: bash
    run: yq -ry '.spec.template.spec.containers[0].image  |="'your_registry'/'your_container_image':'xxxxxxxxxxxxxx'"' /opt/manifests/deployment.yml.tmpl > /opt/manifests/deployment.yml
  env:
    MANIFEST_PATH: manifests
    REGISTRY: your_registry
    CONTAINER_IMAGE: your_container_image


Unable to find image 'linuxserver/yq:2.13.0' locally
2.13.0: Pulling from linuxserver/yq


Digets: 略
Status: Downloaded newer image for linuxserver/yq:2.13.0
usage: yq [-h] [--yaml-output] [--yaml-roundtrip] [--width WIDTH]
          [--indentless-lists] [--in-place] [--version]
          [jq_filter] [files [files ...]]
yq: error: argument files: can't open '/opt/manifests/deployment.yml.tmpl': [Errno 2] No such file or directory: '/opt/manifests/deployment.yml.tmpl'

6.解決策

  • -vオプションで指定するホスト側のパスを「GitHub Actionsのホスト側の 絶対パス 」とする
    • Runnerのワーキングディレクトリは、GITHUB_WORKSPACE で取得できる!
          options: >
-            --rm -v ${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }} ##ホストの相対パス:コンテナ側の絶対パス
+            --rm -v ${{ github.workspace }}/${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }} ##ホストの絶対パス:コンテナ側の絶対パス
            -w=/opt/${{ env.MANIFEST_PATH }}
            --entrypoint yq

7.[備考]GITHUB_WORKSPACEとは

  • GitHubのドキュメントのGITHUB_WORKSPACEの説明文の頼りにすると、Runnerのデフォルトの作業ディレクトリと書かれている

GITHUB_WORKSPACE

The default working directory on the runner for steps, and the default location of your repository when using the checkout action. For example, /home/runner/work/my-repo-name/my-repo-name.

参考:https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables

7-1.GITHUB_WORKSPACE ${{ github.workspace }}をechoしてみる

  • 呼び出すには、${{ github.workspace }} とすればよいので、pwdやlsコマンドと併せて実行してみる
    steps:
      - uses: actions/checkout@v2
      - run: echo -n "github.workspace ${{ github.workspace }}"
      - run: pwd
      - run: ls -la

結果

  • run: echo -n “github.workspace ${{ github.workspace }}”
github.workspace /home/runner/work/actions-dispatch-playground/actions-dispatch-playground
  • run: pwd
/home/runner/work/actions-dispatch-playground/actions-dispatch-playground
  • run: ls -la
total 40
drwxr-xr-x 5 runner docker 4096 Jan 31 02:43 .
drwxr-xr-x 3 runner docker 4096 Jan 31 02:43 ..
drwxr-xr-x 8 runner docker 4096 Jan 31 02:43 .git
drwxr-xr-x 3 runner docker 4096 Jan 31 02:43 .github
-rw-r--r-- 1 runner docker 8429 Jan 31 02:43 .gitignore
-rw-r--r-- 1 runner docker 1069 Jan 31 02:43 LICENSE
-rw-r--r-- 1 runner docker   42 Jan 31 02:43 README.md
drwxr-xr-x 2 runner docker 4096 Jan 31 02:43 manifests

GITHUB_WORKSPACE ${{ github.workspace }}のGitHubのドキュメントで書かれている、

The default working directory on the runner for steps, and the default location of your repository when using the checkout action

とは、リポジトリのルートディレクトリ とみてよさそう。