AWS Glue は、さまざまなデータソースからのデータを大規模に処理・統合できるサーバーレスのデータ統合サービスです。Apache Spark ジョブ用の最新バージョンである AWS Glue 5.0 は、バッチ処理とストリーム処理に最適化された Apache Spark 3.5 ランタイム環境を提供します。AWS Glue 5.0 を使えば、パフォーマンスの向上、セキュリティの強化、次世代の HAQM SageMaker のサポート、その他の機能強化が得られます。AWS Glue 5.0 により、データ統合ワークロードの開発、実行、スケーリングが可能になり、より迅速にインサイトを得られるようになります。
AWS Glue は、複数のジョブ作成アプローチを通じて、さまざまな開発方法に対応しています。ダイレクトコーディングがお好きな開発者の方は、AWS Glue ETL ライブラリを使用した Python または Scala での開発が可能です。
本番環境に耐えうるデータプラットフォームを構築するには、堅牢な開発プロセスと継続的インテグレーションおよびデリバリー (CI/CD) パイプラインが必要です。ローカルマシン、HAQM Elastic Compute Cloud (HAQM EC2) 上の Docker コンテナ、その他の環境など、さまざまな開発ニーズに対応するため、AWS は HAQM ECR Public Gallery を通じて公式の AWS Glue Docker イメージを提供しています。このイメージにより、開発者の方は AWS Glue ETL ライブラリを使用しながら、お好きな環境で効率的に作業できます。
この記事では、Docker コンテナを使用して AWS Glue 5.0 ジョブをローカルで開発およびテストする方法を示します。この記事は、Develop and test AWS Glue version 3.0 and 4.0 jobs locally using a Docker container の更新版で、AWS Glue 5.0 を使用しています。
利用可能な Docker イメージ
以下の Docker イメージが HAQM ECR Public Gallery で利用可能です:
- AWS Glue バージョン 5.0 –
ecr.aws/glue/aws-glue-libs:5
AWS Glue の Docker イメージは、x86_64
と arm64
の両方に対応しています。
この記事では、public.ecr.aws/glue/aws-glue-libs:5
を使用し、コンテナをローカルマシン (Mac、Windows、Linux) 上で実行します。このコンテナイメージは、AWS Glue 5.0 の Spark ジョブでテストされています。このイメージには以下が含まれています。
コンテナをセットアップするには、ECR Public Gallery からイメージを pull し、コンテナを実行します。要件に応じて、次の方法でコンテナの実行方法を示します:
spark-submit
- REPL シェル (
pyspark
)
pytest
- Visual Studio Code
前提条件
始める前に、Docker がインストールされていて Docker デーモンが実行中であることを確認してください。インストール手順については、Mac、Windows、または Linux 向けの Docker ドキュメントを参照してください。また、Docker を実行しているホストに少なくとも 7GB のディスク領域があることを確認してください。
AWS 認証情報の設定
コンテナから AWS API 呼び出しを有効にするには、次の手順で AWS 認証情報を設定します。
- AWS 名前付きプロファイルを作成します。
- Windows では cmd を、Mac/Linux では端末を開き、次のコマンドを実行します:
PROFILE_NAME="profile_name"
次のセクションでは、この AWS 名前付きプロファイルを使用します。
ECR Public Gallery からイメージを pull
Docker を Windows で実行している場合は、イメージを pull する前に Docker アイコンを右クリックし、Linux コンテナに切り替えるを選択してください。
ECR Public Gallery からイメージを pull するには、次のコマンドを実行してください:
docker pull public.ecr.aws/glue/aws-glue-libs:5
コンテナの実行
これで、このイメージを使ってコンテナを実行できます。要件に応じて、以下のいずれかの方法を選択できます。
spark-submit
AWS Glue ジョブスクリプトは、コンテナ上で spark-submit
コマンドを実行することで実行できます。
ジョブスクリプト (sample.py
の例) を書き、次のコマンドを使って /local_path_to_workspace/src/
ディレクトリに保存してください:
$ WORKSPACE_LOCATION=/local_path_to_workspace
$ SCRIPT_FILE_NAME=sample.py
$ mkdir -p ${WORKSPACE_LOCATION}/src
$ vim ${WORKSPACE_LOCATION}/src/${SCRIPT_FILE_NAME}
これらの変数は、次の docker run
コマンドで使用されます。spark-submit
コマンドで使用されるサンプルコード (sample.py
) は、この記事の最後の Appendix に含まれています。
次のコマンドを実行して、コンテナ上で spark-submit
コマンドを実行し、新しい Spark アプリケーションを送信します:
$ docker run -it --rm \
-v ~/.aws:/home/hadoop/.aws \
-v $WORKSPACE_LOCATION:/home/hadoop/workspace/ \
-e AWS_PROFILE=$PROFILE_NAME \
--name glue5_spark_submit \
public.ecr.aws/glue/aws-glue-libs:5 \
spark-submit /home/hadoop/workspace/src/$SCRIPT_FILE_NAME
REPL シェル (pyspark)
REPL (read-eval-print loop) シェルを使用すると、インタラクティブな開発ができます。コンテナ上で pyspark コマンドを実行し、REPL シェルを起動するには、次のコマンドを実行します。
$ docker run -it --rm \
-v ~/.aws:/home/hadoop/.aws \
-e AWS_PROFILE=$PROFILE_NAME \
--name glue5_pyspark \
public.ecr.aws/glue/aws-glue-libs:5 \
pyspark
次の出力が表示されます:
Python 3.11.6 (main, Jan 9 2025, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/__ / .__/\_,_/_/ /_/\_\ version 3.5.2-amzn-1
/_/
Using Python version 3.11.6 (main, Jan 9 2025 00:00:00)
Spark context Web UI available at None
Spark context available as 'sc' (master = local[*], app id = local-1740643079929).
SparkSession available as 'spark'.
>>>
この REPL シェルを使えば、対話的にコーディングとテストができます。
pytest
単体テストには、AWS Glue Spark ジョブスクリプトに対して pytest
を使用できます。
次のコマンドを実行して準備をしてください:
$ WORKSPACE_LOCATION=/local_path_to_workspace
$ SCRIPT_FILE_NAME=sample.py
$ UNIT_TEST_FILE_NAME=test_sample.py
$ mkdir -p ${WORKSPACE_LOCATION}/tests
$ vim ${WORKSPACE_LOCATION}/tests/${UNIT_TEST_FILE_NAME}
次に、docker run
を使って pytest
を呼び出しましょう:
$ docker run -i --rm \
-v ~/.aws:/home/hadoop/.aws \
-v $WORKSPACE_LOCATION:/home/hadoop/workspace/ \
--workdir /home/hadoop/workspace \
-e AWS_PROFILE=$PROFILE_NAME \
--name glue5_pytest \
public.ecr.aws/glue/aws-glue-libs:5 \
-c "python3 -m pytest --disable-warnings"
pytest
がユニットテストの実行を終えると、出力は次のようになります:
============================= test session starts ==============================
platform linux -- Python 3.11.6, pytest-8.3.4, pluggy-1.5.0
rootdir: /home/hadoop/workspace
plugins: integration-mark-0.2.0
collected 1 item
tests/test_sample.py . [100%]
======================== 1 passed, 1 warning in 34.28s =========================
Visual Studio Code
Visual Studio Code でコンテナを設定するには、以下の手順を実行してください:
- Visual Studio Code をインストールしてください。
- Python をインストールしてください。
- Dev Containers をインストールしてください。
- Visual Studio Code でワークスペースフォルダを開いてください。
- Ctrl+Shift+P (Windows/Linux) または Cmd+Shift+P (Mac) を押してください。
Preferences: Open Workspace Settings (JSON)
と入力してください。
- Enter を押してください。
- 次の JSON を入力して保存してください。
{
"python.defaultInterpreterPath": "/usr/bin/python3.11",
"python.analysis.extraPaths": [
"/usr/lib/spark/python/lib/py4j-0.10.9.7-src.zip:/usr/lib/spark/python/:/usr/lib/spark/python/lib/",
]
}
これで、コンテナのセットアップの準備ができました。
- Docker コンテナを実行します:
$ docker run -it --rm \
-v ~/.aws:/home/hadoop/.aws \
-v $WORKSPACE_LOCATION:/home/hadoop/workspace/ \
-e AWS_PROFILE=$PROFILE_NAME \
--name glue5_pyspark \
public.ecr.aws/glue/aws-glue-libs:5 \
pyspark
- Visual Studio Code を起動します。
- ナビゲーションペインで Remote Explorer を選択します。
- コンテナ
ecr.aws/glue/aws-glue-libs:5
を右クリックし、Attach in Current Window を選択します。

-
- 次のダイアログが表示された場合は Got it を選択してください。

/home/hadoop/workspace/
を開いてください。

- AWS Glue の PySpark スクリプトを作成し、Run を選択します。
AWS Glue の PySpark スクリプトが正常に実行されたことが確認できるはずです。

AWS Glue 4.0 と AWS Glue 5.0 の Docker イメージ間の変更点
AWS Glue 4.0 と Glue 5.0 の Docker イメージ間の主な変更点は次のとおりです。
- AWS Glue 5.0 では、バッチジョブとストリーミングジョブの両方に単一のコンテナイメージが使用されます。これは AWS Glue 4.0 とは異なり、4.0 ではバッチ用とストリーミング用に別々のイメージがありました。
- AWS Glue 5.0 では、コンテナのデフォルトユーザー名は hadoop です。AWS Glue 4.0 では、デフォルトユーザー名は glue_user でした。
- AWS Glue 5.0 では、JupyterLab や Livy などのいくつかの追加ライブラリがイメージから削除されています。手動でインストールすることができます。
- AWS Glue 5.0 では、Iceberg、Hudi、Delta ライブラリがすべてデフォルトで事前ロードされており、環境変数
DATALAKE_FORMATS
は不要になりました。AWS Glue 4.0 までは、環境変数 DATALAKE_FORMATS
を使用して、特定のテーブル形式がロードされるかどうかを指定していました。
前述のリストは Docker イメージに固有のものです。AWS Glue 5.0 の更新について詳しくは、Introducing AWS Glue 5.0 for Apache Spark および Migrating AWS Glue for Spark jobs to AWS Glue version 5.0 をご覧ください。
考慮事項
AWS Glue コンテナイメージを使用してジョブスクリプトをローカルで開発する際、以下の機能はサポートされていないことに注意してください:
結論
この投稿では、AWS Glue 5.0 Docker イメージが、お好みの環境で AWS Glue ジョブスクリプトを開発およびテストするための柔軟な基盤を提供することをご紹介しました。HAQM ECR Public Gallery で簡単に入手できるこれらのイメージは、AWS Glue ジョブの開発に一貫したポータブルな環境を提供することで、開発プロセスを合理化します。
エンドツーエンドの開発パイプラインの構築方法の詳細については、End-to-end development lifecycle for data engineers to build a data integration pipeline using AWS Glue をご覧ください。これらの機能を活用し、AWS コミュニティで知見を共有することをお勧めします。
Appendix A: AWS Glue ジョブのテスト用サンプルコード
この Appendix では、テスト目的で AWS Glue ジョブのサンプルコードとして 3 つの異なるスクリプトを紹介します。チュートリアルではこれらのいずれかを使用できます。
以下の sample.py コードは、AWS Glue ETL ライブラリと HAQM Simple Storage Service (HAQM S3) の API 呼び出しを使用しています。このコードには、AWS Identity and Access Management (IAM) での HAQM S3 の権限が必要です。arn:aws:iam::aws:policy/HAQMS3ReadOnlyAccess の IAM 管理ポリシーか、S3 パスに対して ListBucket と GetObject の API 呼び出しを許可するカスタム IAM ポリシーを付与する必要があります。
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions
class GluePythonSampleTest:
def __init__(self):
params = []
if '--JOB_NAME' in sys.argv:
params.append('JOB_NAME')
args = getResolvedOptions(sys.argv, params)
self.context = GlueContext(SparkContext.getOrCreate())
self.job = Job(self.context)
if 'JOB_NAME' in args:
jobname = args['JOB_NAME']
else:
jobname = "test"
self.job.init(jobname, args)
def run(self):
dyf = read_json(self.context, "s3://awsglue-datasets/examples/us-legislators/all/persons.json")
dyf.printSchema()
self.job.commit()
def read_json(glue_context, path):
dynamicframe = glue_context.create_dynamic_frame.from_options(
connection_type='s3',
connection_options={
'paths': [path],
'recurse': True
},
format='json'
)
return dynamicframe
if __name__ == '__main__':
GluePythonSampleTest().run()
以下の test_sample.py コードは、sample.py のユニットテストのサンプルです:
import pytest
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions
import sys
from src import sample
@pytest.fixture(scope="module", autouse=True)
def glue_context():
sys.argv.append('--JOB_NAME')
sys.argv.append('test_count')
args = getResolvedOptions(sys.argv, ['JOB_NAME'])
context = GlueContext(SparkContext.getOrCreate())
job = Job(context)
job.init(args['JOB_NAME'], args)
Appendix B: JDBC ドライバーと Java ライブラリの追加
コンテナ内に現在ない JDBC ドライバーを追加する場合は、ワークスペース内に必要な JAR ファイルを含む新しいディレクトリを作成し、そのディレクトリを docker run
コマンドで /opt/spark/jars/
にマウントします。コンテナ内の /opt/spark/jars/
以下にある JAR ファイルは、自動的に Spark クラスパスに追加され、ジョブ実行中に使用できるようになります。
たとえば、次の docker run
コマンドを使用して、JDBC ドライバーの jar ファイルを PySpark REPL シェルに追加できます:
$ docker run -it --rm \
-v ~/.aws:/home/hadoop/.aws \
-v $WORKSPACE_LOCATION:/home/hadoop/workspace/ \
-v $WORKSPACE_LOCATION/jars/:/opt/spark/jars/ \
--workdir /home/hadoop/workspace \
-e AWS_PROFILE=$PROFILE_NAME \
--name glue5_jdbc \
public.ecr.aws/glue/aws-glue-libs:5 \
pyspark
前述のように、customJdbcDriverS3Path
接続オプションは、AWS Glue コンテナイメージにカスタム JDBC ドライバを HAQM S3 からインポートするために使用できません。
Appendix C: Livy と JupyterLab の追加
AWS Glue 5.0 コンテナイメージには、デフォルトで Livy がインストールされていません。AWS Glue 5.0 コンテナイメージを基本とする新しいコンテナイメージを作成できます。次の Dockerfile は、開発およびテスト体験を強化するために必要な追加コンポーネントを含めるように Docker イメージを拡張する方法を示しています。
始めるには、ワークステーションにディレクトリを作成し、そのディレクトリに Dockerfile.livy_jupyter
ファイルを配置します。
$ mkdir -p $WORKSPACE_LOCATION/jupyterlab/
$ cd $WORKSPACE_LOCATION/jupyterlab/
$ vim Dockerfile.livy_jupyter
次のコードは Dockerfile.livy_jupyter
です:
FROM public.ecr.aws/glue/aws-glue-libs:5 AS glue-base
ENV LIVY_SERVER_JAVA_OPTS="--add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/sun.nio.cs=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED"
# Download Livy
ADD --chown=hadoop:hadoop http://dlcdn.apache.org/incubator/livy/0.8.0-incubating/apache-livy-0.8.0-incubating_2.12-bin.zip ./
# Install and configure Livy
RUN unzip apache-livy-0.8.0-incubating_2.12-bin.zip && \
rm apache-livy-0.8.0-incubating_2.12-bin.zip && \
mv apache-livy-0.8.0-incubating_2.12-bin livy && \
mkdir -p livy/logs && \
cat <> livy/conf/livy.conf
livy.server.host = 0.0.0.0
livy.server.port = 8998
livy.spark.master = local
livy.repl.enable-hive-context = true
livy.spark.scala-version = 2.12
EOF && \
cat <> livy/conf/log4j.properties
log4j.rootCategory=INFO,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
log4j.logger.org.eclipse.jetty=WARN
EOF
# Switching to root user temporarily to install dev dependency packages
USER root
RUN dnf update -y && dnf install -y krb5-devel gcc python3.11-devel
USER hadoop
# Install SparkMagic and JupyterLab
RUN export PATH=$HOME/.local/bin:$HOME/livy/bin/:$PATH && \
printf "numpy<2\nIPython<=7.14.0\n" > /tmp/constraint.txt && \
pip3.11 --no-cache-dir install --constraint /tmp/constraint.txt --user pytest boto==2.49.0 jupyterlab==3.6.8 IPython==7.14.0 ipykernel==5.5.6 ipywidgets==7.7.2 sparkmagic==0.21.0 jupyterlab_widgets==1.1.11 && \
jupyter-kernelspec install --user $(pip3.11 --no-cache-dir show sparkmagic | grep Location | cut -d" " -f2)/sparkmagic/kernels/sparkkernel && \
jupyter-kernelspec install --user $(pip3.11 --no-cache-dir show sparkmagic | grep Location | cut -d" " -f2)/sparkmagic/kernels/pysparkkernel && \
jupyter server extension enable --user --py sparkmagic && \
cat <> /home/hadoop/.local/bin/entrypoint.sh
#!/usr/bin/env bash
mkdir -p /home/hadoop/workspace/
livy-server start
sleep 5
jupyter lab --no-browser --ip=0.0.0.0 --allow-root --ServerApp.root_dir=/home/hadoop/workspace/ --ServerApp.token='' --ServerApp.password=''
EOF
# Setup Entrypoint script
RUN chmod + x /home/hadoop/.local/bin/entrypoint.sh
# Add default SparkMagic Config
ADD --chown=hadoop:hadoop http://raw.githubusercontent.com/jupyter-incubator/sparkmagic/refs/heads/master/sparkmagic/example_config.json .sparkmagic/config.json
# Update PATH var
ENV PATH=/home/hadoop/.local/bin:/home/hadoop/livy/bin/:$PATH
ENTRYPOINT ["/home/hadoop/.local/bin/entrypoint.sh"]
Docker ビルドコマンドを実行してイメージをビルドします:
docker build \
-t glue_v5_livy \
--file $WORKSPACE_LOCATION/jupyterlab/Dockerfile.livy_jupyter \
$WORKSPACE_LOCATION/jupyterlab/
イメージのビルドが完了したら、次の docker run コマンドを使用して、新しく作成されたイメージを起動できます。
docker run -it --rm \
-v ~/.aws:/home/hadoop/.aws \
-v $WORKSPACE_LOCATION:/home/hadoop/workspace/ \
-p 8998:8998 \
-p 8888:8888 \
-e AWS_PROFILE=$PROFILE_NAME \
--name glue5_jupyter \
glue_v5_livy

Appendix D: 追加の Python ライブラリの追加
このセクションでは、追加の Python ライブラリを追加し、Python パッケージをインストールする方法について説明します。
ローカル Python ライブラリ
ローカルの Python ライブラリを追加するには、ディレクトリに配置し、パスを $EXTRA_PYTHON_PACKAGE_LOCATION
に割り当ててください:
$ docker run -it --rm \
-v ~/.aws:/home/hadoop/.aws \
-v $WORKSPACE_LOCATION:/home/hadoop/workspace/ \
-v $EXTRA_PYTHON_PACKAGE_LOCATION:/home/hadoop/workspace/extra_python_path/ \
--workdir /home/hadoop/workspace \
-e AWS_PROFILE=$PROFILE_NAME \
--name glue5_pylib \
public.ecr.aws/glue/aws-glue-libs:5 \
-c 'export PYTHONPATH=/home/hadoop/workspace/extra_python_path/:$PYTHONPATH ; pyspark'
PYTHONPATH
にパスが追加されたことを検証するには、sys.path
にそのパスが存在するかどうかを確認できます:
Python 3.11.6 (main, Jan 9 2025, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/__ / .__/\_,_/_/ /_/\_\ version 3.5.2-amzn-1
/_/
Using Python version 3.11.6 (main, Jan 9 2025 00:00:00)
Spark context Web UI available at None
Spark context available as 'sc' (master = local[*], app id = local-1740719582296).
SparkSession available as 'spark'.
>>> import sys
>>> "/home/hadoop/workspace/extra_python_path" in sys.path
True
Python パッケージの pip によるインストール
PyPI (または他のアーティファクトリポジトリ) からパッケージを pip でインストールするには、次のアプローチを使用できます。
docker run -it --rm \
-v ~/.aws:/home/hadoop/.aws \
-v $WORKSPACE_LOCATION:/home/hadoop/workspace/ \
--workdir /home/hadoop/workspace \
-e AWS_PROFILE=$PROFILE_NAME \
-e SCRIPT_FILE_NAME=$SCRIPT_FILE_NAME \
--name glue5_pylib \
public.ecr.aws/glue/aws-glue-libs:5 \
-c 'pip3 install snowflake==1.0.5 ; spark-submit /home/hadoop/workspace/src/$SCRIPT_FILE_NAME'
本記事は、2025 年 3 月 12 日に公開された Develop and test AWS Glue 5.0 jobs locally using a Docker container を翻訳したものです。翻訳はソリューションアーキテクトの高橋が担当しました。