💭

WSL2のUbuntu 20.04でLocalStackを使ってみる

2021/12/14に公開

はじめに

LocalStackはAWSアプリケーションやLambdaをローカル環境で動かすためのソリューション。
オープンソース版では制限があるがPro版だと多くのサービスをサポートしている。[1]
今回は、WSL2上のUbuntu 20.04にDockerを追加ってLocalStackを動かしてみた。

↓cloud-initを使用して、WSL2のセットアップを簡略化した方法も書きました。
https://zenn.dev/s_ryuuki/articles/46c6d9d8d34404

動作確認環境

Host OS

  • Windows 10 バージョン: 21H1 / OSビルド: 19043.1348
  • Windows Terminal 1.11.2921.0

Guest OS (WSL2)

  • Ubuntu 20.04
    • Docker: 20.10.11
    • Python: 3.8.10
    • docker-compose: 1.29.2
    • LocalStack: 0.13.1
    • aws-cli: 2.4.5

Ubuntu-20.04の準備

Ubuntu-20.04をインストールと起動

ディストリビューション一覧を表示。

PS C:\Users\hoge> wsl --list --online
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl --install -d <Distro>' を使用してインストールします。

NAME            FRIENDLY NAME
Ubuntu          Ubuntu
Debian          Debian GNU/Linux
kali-linux      Kali Linux Rolling
openSUSE-42     openSUSE Leap 42
SLES-12         SUSE Linux Enterprise Server v12
Ubuntu-16.04    Ubuntu 16.04 LTS
Ubuntu-18.04    Ubuntu 18.04 LTS
Ubuntu-20.04    Ubuntu 20.04 LTS

Ubuntu-20.04をインストール。

PS C:\Users\hoge> wsl --install -d Ubuntu-20.04
ダウンロード中: Ubuntu 20.04 LTS
インストール中: Ubuntu 20.04 LTS
Ubuntu 20.04 LTS はインストールされました。
Ubuntu 20.04 LTS を起動しています...

[ex] Ubuntu-20.04をアンインストールする。

PS C:\Users\hoge> wsl --shutdown
PS C:\Users\hoge> wsl --unregister Ubuntu-20.04

Ubuntu 20.04の設定

ユーザー名とパスワードを設定する。[2]

Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: hoge
New password:****
Retype new password:****
passwd: password updated successfully
Installation successful!
To run a command as administrator (user "root"), use "sudo 
 〜中略〜 
This message is shown once once a day. To disable it please create the
/home/hoge/.hushlogin file.
hoge@AA:~$

BashとvimのBeep音を止める。

hoge@AA:~$ echo "set bell-style none" >> ~/.inputrc
hoge@AA:~$ echo "set visualbell t_vb=" >> ~/.vimrc

パッケージのインデックスをアップデートする。

hoge@AA:~$ sudo apt -y update
[sudo] password for hoge:
 〜中略〜 
Reading package lists... Done
Building dependency tree
Reading state information... Done
251 packages can be upgraded. Run 'apt list --upgradable' to see them.

パッケージをアップデートする。

hoge@AA:~$ sudo apt -yV upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
The following NEW packages will be installed:
   distro-info (0.23ubuntu1)
 〜中略〜 
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

ツールのインストール

zipファイルを扱うためにインストールする。

hoge@AA:~$ sudo apt -y install zip

LocalStackレスポンスのjsonを確認するためにインストールする。

hoge@AA:~$ sudo apt -y install jq

再起動する

hoge@AA:~$ exit

状態を確認する。

PS C:\Users\hoge> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-20.04    Running         2

停止する。

PS C:\Users\hoge> wsl -t Ubuntu-20.04

起動する。

PS C:\Users\hoge> wsl ~
hoge@AA:~$

必要に応じてスナップショットを作っておくと良い。[3]

Dockerの準備

インストールする

必要なソフトを追加する。

hoge@AA:~$ sudo apt -y install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release

GPGキー追加する。

hoge@AA:~$  curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Dockerのパッケージリポジトリをaptに追加する。

hoge@AA:~$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker Engineをインストールする。

hoge@AA:~$ sudo apt update
hoge@AA:~$ sudo apt -y install docker-ce docker-ce-cli containerd.io

docker-composeをインストールする。

hoge@AA:~$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
hoge@AA:~$ sudo chmod +x /usr/local/bin/docker-compose
hoge@AA:~$ docker-compose --version
docker-compose version 1.29.2, build 5becea4c

サービスを起動する

Docker Daemonを起動する。

hoge@AA:~$ sudo service docker start

[ex]ログイン時にサービスを起動する[4]

sudo設定ファイルを開く。

hoge@AA:~$ sudo visudo

最後の行にdockerの設定を追加する。「hoge」は自分の使用ユーザー名に変更すること。

hoge ALL=NOPASSWD: /usr/sbin/service docker start, /usr/sbin/service docker stop, /usr/sbin/service docker restart

保存して終了する。Ctrl(control)+x、y、Enter。

.bashrcに設定を追加する。

echo 'service docker status > /dev/null 2>&1
if [ $? = 1 ]; then
    sudo service docker start
fi' >> ~/.bashrc

ログイン時に起動するかテストする。

hoge@AA:~$ sudo service docker stop
 * Stopping Docker: docker               [ OK ]
hoge@AA:~$ exit
PS C:\Users\hoge> wsl ~
 * Starting Docker: docker               [ OK ]

ユーザーが操作できるように設定する

dockerグループにユーザーを追加する。「hoge」は設定したユーザー名に置き換えること。

hoge@AA:~$ sudo usermod -aG docker hoge
hoge@AA:~$ exit
PS C:\Users\hoge> wsl ~

起動テストをする

Dockerでhello-worldを実行できるか確認する。[5]

hoge@AA:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
〜中略〜
Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

LocalStackの準備

docker-compose.ymlを準備する

LocalStackをGitHubからダウンロードして解凍する。[6]

hoge@AA:~$ curl -L -O https://github.com/localstack/localstack/archive/refs/tags/v0.13.0.zip
hoge@AA:~$ unzip v0.13.0.zip

docker-compose.ymlを編集する

hoge@AA:~$ vi localstack-0.13.0/docker-compose.yml

変更点
v0.13.1に固定。Pro用の設定を削除。IP設定(127.0.0.1:)削除[7][8]。Lambda用設定のLAMBDA_EXECUTORを追加。[9]

docker-compose.yml 編集後の状態
version: "3.8"

services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
    image: localstack/localstack:0.13.1
    network_mode: bridge
    ports:
      - "4566:4566"
      - "4571:4571"
    environment:
      - SERVICES=${SERVICES- }
      - DEBUG=${DEBUG- }
      - DATA_DIR=${DATA_DIR- }
      - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR- }
      - LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY- }  # only required for Pro
      - HOST_TMP_FOLDER=${TMPDIR:-/tmp/}localstack
      - DOCKER_HOST=unix:///var/run/docker.sock
      - LAMBDA_EXECUTOR=docker-reuse
    volumes:
      - "${TMPDIR:-/tmp}/localstack:/tmp/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"

docker-compose.ymlの編集を保存して終了する。(viだとescキーを押す。「:wq」を入力してエンターキーを押す。)

起動する

docker-composeを使って起動する。[10]

hoge@AA:~$ cd localstack-0.13.0
hoge@AA:~/localstack-0.13.0$ docker-compose up -d
Pulling localstack (localstack/localstack:)...
a10c77af2613: Pull complete
 〜中略〜 
Digest: sha256:3fcef2507cd96b64a5efd94ab25e95fa58b46e97c1217e3c0e3cec352d8376ee
Status: Downloaded newer image for localstack/localstack:0.13.1
Creating localstack_main ... done

起動状況を確認をする。

hoge@AA:~/localstack-0.13.0$ docker-compose ps
     Name               Command          State                                              Ports
---------------------------------------------------------------------------------------------------------------------------------------------
localstack_main   docker-entrypoint.sh   Up      0.0.0.0:4566->4566/tcp,:::4566->4566/tcp, 0.0.0.0:4571->4571/tcp,:::4571->4571/tcp, 5678/tcp

[ex] docker-composeを使って停止する。

hoge@AA:~/localstack-0.13.0$ docker-compose down

サービスの起動状況チェック

LocalStackで使用できるサービスの起動状況を確認する。[11]

hoge@AA~/localstack-0.13.0$  curl -s http://localhost:4566/health | jq
{
  "features": {
    "initScripts": "initialized"
  },
  "services": {
    "acm": "available",
    "apigateway": "available",
    "cloudformation": "available",
    "cloudwatch": "available",
    "config": "available",
    "dynamodb": "available",
    "dynamodbstreams": "available",
    "ec2": "available",
    "es": "available",
    "events": "available",
    "firehose": "available",
    "iam": "available",
    "kinesis": "available",
    "kms": "available",
    "lambda": "available",
    "logs": "available",
    "redshift": "available",
    "resource-groups": "available",
    "resourcegroupstaggingapi": "available",
    "route53": "available",
    "route53resolver": "available",
    "s3": "available",
    "secretsmanager": "available",
    "ses": "available",
    "sns": "available",
    "sqs": "available",
    "ssm": "available",
    "stepfunctions": "available",
    "sts": "available",
    "support": "available",
    "swf": "available"
  }
}

LocalStackへアクセスする

AWS CLI Version 2セットアップ

awscliをダウンロードをしてインストールする。[12]

hoge@AA:~$ cd
hoge@AA:~$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
hoge@AA:~$ unzip awscliv2.zip
hoge@AA:~$ sudo ./aws/install
hoge@AA:~$ aws --version
aws-cli/2.4.5 Python/3.8.8 Linux/5.10.16.3-microsoft-standard-WSL2 exe/x86_64.ubuntu.20 prompt/off
hoge@AA:~$ rm -fr aws
hoge@AA:~$ rm awscliv2.zip

awscli-localをインストールする。

hoge@AA:~$ sudo apt -y install python3-pip
hoge@AA:~$ pip3 install awscli-local

コマンドが実行できるようにPATHを通す。

hoge@AA:~$ echo 'export PATH="$PATH:~/.local/bin"' >> ~/.bashrc
hoge@AA:~$ source ~/.bashrc

LocalStack接続用のダミー設定を作る。

hoge@AA:~$ aws configure --profile=localstack
AWS Access Key ID [None]: dummy
AWS Secret Access Key [None]: dummy
Default region name [None]: ap-northeast-1
Default output format [None]: json

S3

作成したバケットや追加したファイルは「docker-compose down」すると消えます。[13]

hoge-bucketバケットを作成する。

hoge@AA:~$ awslocal s3 mb s3://hoge-bucket --profile=localstack
make_bucket: hoge-bucket

hoge-bucketバケットが作成されていることを確認する。

hoge@AA:~$ awslocal s3 ls --profile=localstack
2020-09-02 22:36:16 hoge-bucket

hoge-bucketバケットにファイル追加と確認をする。

hoge@AA:~$ echo 'Test Hoge Hoge!' > hoge.txt
hoge@AA:~$ awslocal s3 cp hoge.txt s3://hoge-bucket --profile=localstack
upload: ./hoge.txt to s3://hoge-bucket/hoge.txt
hoge@AA:~$ awslocal s3 ls s3://hoge-bucket --profile=localstack
2020-09-02 22:38:45         16 hoge.txt

Lambda

Lambda Functionの準備

コードを作成します。

hoge@AA:~$ vi myFunction.py

S3で作った「hoge-bucket」バケットあることが前提のコードになっています。[14]

myFunction.py
import os
import boto3
from boto3.session import Session
from datetime import datetime

session = Session(
    aws_access_key_id='dummy',
    aws_secret_access_key='dummy',
    region_name='ap-northeast-1'
)

if os.getenv('LOCALSTACK_HOSTNAME') is None:
    endpoint = 'http://localhost:4566'
else:
    endpoint=f"http://{os.environ['LOCALSTACK_HOSTNAME']}:4566"

s3 = session.resource(
    service_name='s3', 
    endpoint_url=endpoint
)

def lambda_handler(event, context):

    bucket = 'hoge-bucket'
    key = datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt'
    file_contents = 'Python Lambda Save File'

    s3.Bucket(bucket).put_object(Key=key, Body=file_contents)

    return 'create file '+ key

myFunction.pyの編集を保存して終了する。(viだとescキーを押す。「:wq」を入力してエンターキーを押す。)

zip形式で圧縮をする。

hoge@AA:~$ zip lambda.zip myFunction.py

Lambdaへの登録と実行

Functionを登録する。[15]

hoge@AA:~$ awslocal lambda create-function --function-name myFunction  --runtime python3.8 --handler myFunction.lambda_handler --role r1  --zip-file fileb://lambda.zip --profile=localstack
{
    "FunctionName": "myFunction",
    "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:myFunction",
    "Runtime": "python3.8",
    "Role": "r1",
    "Handler": "myFunction.lambda_handler",
    "CodeSize": 592,
    "Description": "",
    "Timeout": 3,
    "LastModified": "2020-10-03T08:20:15.032+0000",
    "CodeSha256": "SuHNSoLMS/zBPGAKiezjN/qL10Nntx2b3o5Z3SSivWY=",
    "Version": "$LATEST",
    "VpcConfig": {},
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "a8380dc0-349f-4be4-949c-065a90431750",
    "State": "Active",
    "LastUpdateStatus": "Successful",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ]
}

Functionを実行する。[16]

hoge@AA:~$ awslocal lambda invoke --cli-binary-format raw-in-base64-out --function-name myFunction --profile=localstack result.log
hoge@AA:~$ cat result.log | jq
"create file2020-10-02-08-35-49.txt"

S3にファイルが追加されているか確認する。

hoge@AA:~$ awslocal s3 ls s3://hoge-bucket --profile=localstack
2020-10-02 08:35:49         23 2020-10-02-08-35-49.txt

[ex]LocalStackをdockerのみで動作させる

docker-composeを使わないで動作させる。[17]
dockerグループ追加、python3-pipインストール、「~/.local/bin」へのPATHを通すなどが終わっている必要がある。

LocalStackをインストールする。

hoge@AA:~$ pip3 install localstack==0.13.1

エラー[18]が出るためdocker-composeを実行した時にできたファイルを削除しておく。

hoge@AA:~$ sudo rm -fr /tmp/localstack/

LocalStackを実行する。
初回はdocker imageのダウンロードされるため時間がかかる。

hoge@AA:~$ LAMBDA_EXECUTOR=docker-reuse SERVICES=s3,lambda DEBUG=1 localstack start

起動したらS3やLambdaへのアクセスができるようになる。
Ctrl(control)+cで停止する。

参考にしたサイト

WSL2

Docker

LocalStack

脚注
  1. AWS Service Feature Coverage | LocalStack Docs ↩︎

  2. コマンドプロンプトで立ち上がる。設定後はWindows Terminalで作業した方が良い。 ↩︎

  3. グチャグチャになった「Ubuntu on WSL2」のやり直し方 - Qiita ↩︎

  4. 環境をインポートした場合うまく動かない? ↩︎

  5. グループ追加できていないとエラーが出る→ docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied. ↩︎

  6. docker-compose.ymlが必要なだけなので他の取得方法でも良い。 ↩︎

  7. localhostではなくIP指定でアクセスする必要がある。shellでIPアドレスは「ip addr」で確認できる。 ↩︎

  8. さらに別のPCからアクセスしたい場合はポートフォワードとファイアウォールの設定が必要。WSL2で起動したサーバーに外部の端末からアクセスする – GUNMA GIS GEEK ↩︎

  9. AMBDA_DOCKER_NETWORK=hostを設定すると「listen tcp :9001: bind: address already in use」エラーになる。 ↩︎

  10. docker-compose up」を「-d」なしで起動するとログが確認できる。 ↩︎

  11. サービスが起動するまで時間がかかりエラーになることもある。その場合は少し時間を空けてアクセスする。 ↩︎

  12. Linux での AWS CLI バージョン 2 のインストール、更新、アンインストール - AWS Command Line Interface ↩︎

  13. 永続化する設定もある。 LocalStackに保存するデータを永続化する - CLOVER🍀 ↩︎

  14. Lambda functionからS3やDynamoDBにアクセスする場合はos.environ['LOCALSTACK_HOSTNAME']でホスト名取得してendpointを設定する必要がある。 ↩︎

  15. --handler myFunction.lambda_handlerはファイル名.ファンクション名で指定する必要がある。 ↩︎

  16. 初回はdocker imageのダウンロードが走るため起動まで少し時間がかかる。 ↩︎

  17. 起動中の場合は「docker-compose down」で止めておくこと。 ↩︎

  18. PermissionError: [Errno 13] Permission denied: '/tmp/localstack/cache' ↩︎

Discussion