SmartHR Tech Blog

SmartHR 開発者ブログ

Citus の docker image で locale / collation を設定する

はじめに

こんにちは、バックエンドエンジニアの神崎 (@tknzk) です。 今回は、今年6月に SmartHR に投入された Citus を運用したり開発環境で利用する際に問題になった locale について書きます。

問題

Citus に移行して、大小の問題が発生しました。 その一つに locale の設定漏れによる sort が意図しないケースというものがあります。 問題を調査していくと、 locale の設定が en_US.utf-8 になっているのが原因でした。

この問題を解決するため、 locale の設定、 collation の設定を行うことになりました。

開発環境

問題を解消するに当たり、まずは、開発環境で問題を解消できるか開発、検証する必要があります。 SmartHR では開発環境として、Citus Data 社が提供している docker image をつかっており その中身は postgres の image に citus extension が組み込まれたものになります。

実際には citus image x 2 (master/worker) と citus-manager を稼働させて開発に利用しています。 Citus Data 社の提供する docker image は、locale の設定がされておらず、collation の設定を行う sql を実行すると、エラーになる問題が発生しました。 そのため、collation の設定ができるような docker image を使う必要が出てきました。

production の cituscloud について

開発環境の docker image は locale の設定が必要でしたがが、実は production 環境である Citus Cloud は locale の設定がしてあり、collation を設定する SQL はそのまま実行できたのでした。

とはいえ、cituscloud を開発環境で利用するにはコストがかさむので開発環境で利用する docker image でも collation の設定ができるようにする必要があります。

locale を組み込む

  • Citus Data 社の docker image は ベースは postgres の image なので、locale の設定も、その手順に習って行いたいと思います。

  • https://hub.docker.com/_/postgres/

You can also extend the image with a simple Dockerfile to set a different locale. The following example will set the default locale to de_DE.utf8:

FROM postgres:9.4
RUN localedef -i de_DE -c -f UTF-8 -A /usr/share/locale/locale.alias de_DE.UTF-8
ENV LANG de_DE.utf8
Since database initialization only happens on container startup, this allows us to set the language before it is created.

locale 反映版の Dockerfile

FROM postgres:11
ARG VERSION=8.0.0-1
LABEL maintainer="Citus Data https://citusdata.com" \
      org.label-schema.name="Citus" \
      org.label-schema.description="Scalable PostgreSQL for multi-tenant and real-time workloads" \
      org.label-schema.url="https://www.citusdata.com" \
      org.label-schema.vcs-url="https://github.com/citusdata/citus" \
      org.label-schema.vendor="Citus Data, Inc." \
      org.label-schema.version=${VERSION} \
      org.label-schema.schema-version="1.0"

# we released 8.0.0-1 version for docker image to update postgresql-hll
# however, citus itself does not have 8.0.0-1 version so we are
# hardcoding version number here. In the future we should change
# hardcoded part to use $VERSION instead
ENV CITUS_VERSION 8.0.0.citus-1

# install Citus
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
       ca-certificates \
       curl \
    && curl -s https://install.citusdata.com/community/deb.sh | bash \
    && apt-get install -y postgresql-$PG_MAJOR-citus-8.0=$CITUS_VERSION \
                          postgresql-$PG_MAJOR-hll=2.12.citus-1 \
                          postgresql-$PG_MAJOR-topn=2.2.0 \
    && apt-get purge -y --auto-remove curl \
    && rm -rf /var/lib/apt/lists/*

# set locale
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
# ENV LANG ja_JP.utf8

# add citus to default PostgreSQL config
RUN echo "shared_preload_libraries='citus'" >> /usr/share/postgresql/postgresql.conf.sample

# add scripts to run after initdb
COPY 000-configure-stats.sh 001-create-citus-extension.sql 002-create-collation.sql /docker-entrypoint-initdb.d/

# add health check script
COPY pg_healthcheck /

HEALTHCHECK --interval=4s --start-period=6s CMD ./pg_healthcheck
BEGIN;
CREATE COLLATION "ja_JP.utf8" (locale = "ja_JP.UTF-8");

COMMIT;
  • もともとの Dockerfile からの変更点は、 localedef の部分と collation の設定 script の追加です。 上記の Dockerfile をつかって image を build し、開発環境に利用することで、collation の設定をおこなう SQL が実行できるようになりました。

まとめ

もともとの問題となっていた、sort の問題も collation の設定で解決できました。 また、開発で利用している、docker image も中身がどのようなものになっているかを把握できました。

We are hiring!

Citus を production で運用しつつ、マルチテナントウェブアプリケーションを開発するエンジニアを募集中です!

https://open.talentio.com/1/c/smarthr/requisitions/detail/6632/open.talentio.com

会社説明資料

https://speakerdeck.com/miyasho88/we-are-hiring

ご連絡お待ちしています!