LocalStackのv4.14.0のコンテナイメージをビルドしてghcr.ioにPushする

LocalStackのv4.14.0のコンテナイメージをビルドしてghcr.ioにPushする

2026.04.07

こんばんは、情報システム部の夏目です。

先月LocalStackがCommunity Editionを廃止して、商用利用では有料プランが必要になりました。

Flociなどの代替となるOSSプロジェクトも出てきたので、今後はそちらを使うべきだと思われます。

https://dev.classmethod.jp/articles/floci-localstack-alternative-aws-emulator-try/

ただ、一部機能が足りていないこともあるので、しばらくはLocalStackを使い続けないといけないこともあるかと思います。

なので、今回はGithub ActionsでLocalStack v4.14.0のコンテナイメージをビルドして使えるようにしてみます。

なぜコンテナイメージをビルドするのか

LocalStack Community Editionのコード(ここでは v4.14.0のコード)はApache 2.0ライセンスなので利用に問題ないように見えます。

しかしDocker Hubからpullして利用する行為はLocalStackの配布サービスを利用していることになり、LocalStackの現在の利用規約が適用される可能性があります。

また、LocalStackの公式発表では旧バージョンのイメージはDocker Hubで引き続き利用可能だとは述べていますが、旧バージョンの商用利用に関する利用規約の適用範囲については明確な言及がありません。

そのためv4.14.0のソースコードからコンテナイメージをビルドするのが、法的リスクを最小化するのに有用、だそうです。

LocalStack v4.14.0のコンテナイメージをビルドする

今回はLocalStackのCommunity EditionのコードをForkして、Github Actionsでビルドを行い、ghcr.ioにPushしてみます。

LocalStackをフォークする

https://github.com/localstack/localstack にアクセスして、Forkをします。

38e40721-59a4-42ad-9cd1-ba51d462702a

Forkのボタンをクリックするだけで良いのですが、その後の操作で注意があります。

f253e852-df1d-4190-bcbf-78fee874ab43

下部にある Copy the main branch only のチェックボックスにチェックが入っているので外します。
このチェックが入ったままだと、タグの情報も消去されてしまうためです。

ここでは localstack-my-archive という名前でフォークします。

19573493-211e-4ac4-a74c-c99f5603cfec

Github Actionsでビルドさせるワークフローを書くので、CloneのためにURIをコピーします。

Cloneして最低限の準備をする

$ git clone --depth 1 --branch v4.14.0 --single-branch git@github.com:sinofseven/localstack-my-archive.git

上記gitコマンドでv4.14.0のコードをCloneします。

$ cd localstack-my-archive
$ git log -1
commit 3d5a0c70e0fe2eb0864447c882454d33b406ba8a
Author: localstack[bot] <localstack-bot@users.noreply.github.com>
Date:   2026-02-26 10:14:34 +0000

    release version 4.14.0

今v4.14.0のコミットであることがわかります。

$ git checkout -b my-archive-4.14.0

今HEADなので、このコミットにブランチを生やします。
ここでは my-archive-4.14.0 という名前にします。

$ git rm .github/workflows/*.yml
$ git commit -m 'delete all workflow'

元々あるGithub Actionsのワークフローは不必要なので削除し、コミットします。
Scheduleで動くものもあるので、置いておくのはちょっと不安だったので削除します。

$ git push origin my-archive-4.14.0

一旦、このブランチをPushします。
また、このブランチをデフォルトブランチにします。
(ScheduleトリガーのGihtub Actionsはデフォルトブランチのものが実行されるので)

9eb71ce1-2084-4fa1-9ba0-96576c286289

Settings -> General -> Default branch において、 左右の矢印が並んだボタンをクリックします。

043711e9-84f1-48c6-964b-f4a34262bb3e

my-archive-4.14.0 を選択して Update をクリックします。

Changing your default branch can have unintended consequences that can affect new pull requests and clones.

デフォルトブランチを変更すると、予期せぬ影響が生じ、新規のプルリクエストやクローンに支障をきたす可能性があります。

警告が出ますが、 I understand, update the default branch. をクリックします。

a66a0f8c-361f-4109-9b69-32c9f9276037

これでデフォルトブランチが my-archive-4.14.0 になりました。

Dockerfileを少し更新する

自分が手元で試したときには、このままではイメージのビルドができませんでした。

なので、一部修正します。

Dockerfile
diff --git a/Dockerfile b/Dockerfile
index f843982..f28b63a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -49,6 +49,7 @@ RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \
   && rm "$LATEST_VERSION_FILENAME.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
   && ln -s /usr/local/bin/node /usr/local/bin/nodejs \
   # upgrade npm to the latest version
+  && npm install -g npm@11.11.0 \
   && npm install -g npm@latest \
   # smoke tests
   && node --version \

これはNode.js v22.22.2に同梱されているnpmを最新バージョンにアップグレードする際、新しいnpmが promise-retry をバンドルしなくなったため、書き換え後にnpmのコードが遅延ロードしようとして MODULE_NOT_FOUND のエラーが出てしまうためです。

$ git commit -a -m 'update Dockerfile'
$ git push origin my-archive-4.14.0

コミットして、プッシュします。

Github Actionsのワークフローを作成する

ワークフロー全文

.github/workflows/build_image.yml
name: build-image

on:
  push:
    branches:
      - my-archive-4.14.0

jobs:
  build:
    permissions:
      contents: read
      packages: write
    strategy:
      matrix:
        runner:
          - ubuntu-24.04
          - ubuntu-24.04-arm
        include:
          - runner: ubuntu-24.04
            tag: 4.14.0-amd64
          - runner: ubuntu-24.04-arm
            tag: 4.14.0-arm64
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Setup python
        uses: actions/setup-python@v6
        with:
          python-version-file: .python-version

      - name: install dependencies
        run: make install

      - name: install setuptools
        run: |
          . .venv/bin/activate
          pip install --upgrade setuptools setuptools_scm

      - name: Build image
        run: |
          . .venv/bin/activate
          make docker-build

      - name: Login to ghcr.io
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Push to ghcr.io
        run: |
          docker tag \
            localstack/localstack:latest \
            ghcr.io/${{ github.repository_owner }}/localstack-my-archive:${{ matrix.tag }}

          docker image push \
            ghcr.io/${{ github.repository_owner }}/localstack-my-archive:${{ matrix.tag }}

x86_64とarm64でビルド

    strategy:
      matrix:
        runner:
          - ubuntu-24.04
          - ubuntu-24.04-arm
        include:
          - runner: ubuntu-24.04
            tag: 4.14.0-amd64
          - runner: ubuntu-24.04-arm
            tag: 4.14.0-arm64
    runs-on: ${{ matrix.runner }}

今回x86_64とarm64両方のコンテナイメージをビルドさせます。
strategyを使って、x86_64とarm64のRunnerを使ってビルドします。

docker buildxとか使う方法のあるでしょうが、今回は make docker-build (bin/docker-helper.sh)でビルドする想定なので、この形式にしています。

Pythonにおいて依存関係のインストール

      - name: install dependencies
        run: make install

      - name: install setuptools
        run: |
          . .venv/bin/activate
          pip install --upgrade setuptools setuptools_scm

make installを実行することで、 .venv という仮想環境を作りそこに依存ライブラリをインストールします。

ただ、コンテナをビルドする際に setuptools_scm を使用していますが、 make install ではインストールされないので別ステップでインストールを行っています。

ghcr.ioへのPush

      - name: Build image
        run: |
          . .venv/bin/activate
          make docker-build

      - name: Login to ghcr.io
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Push to ghcr.io
        run: |
          docker tag \
            localstack/localstack:latest \
            ghcr.io/${{ github.repository_owner }}/localstack-my-archive:${{ matrix.tag }}

          docker image push \
            ghcr.io/${{ github.repository_owner }}/localstack-my-archive:${{ matrix.tag }}

make docker-build が成功すると localstack/localstack:latest というコンテナイメージが作成されます。

このイメージを docker tag コマンドで、ghcr.io向けのタグに変更してからpushします。

ghcr.ioにpushするにはghcr.ioに対して認証を通す必要があるので、 docker/login-action で認証をしています。

今回は localstack-my-archive という名前のコンテナイメージとして、 4.14.0-amd644.14.0-arm64 という名前のタグを作っています。

確認してみる

f28956e3-1146-4e30-be1d-63b993af158d

右下を見ると Packageslocalstack-my-archive というのが増えています。

8e0fec24-96d9-4a91-af03-922c0d2a955e

4.14.0-amd644.14.0-arm64 というタグが存在していることがわかります。

まとめ

その場しのぎではありますが、当面の間LocalStackをしようするためにソースコードからコンテナイメージをビルドしてみました。

flociなどが機能拡充して、早く使わずにすむようになればと思います。

この記事をシェアする

関連記事