ロケールと言語およびタイムゾーンを日本仕様に設定する

# はじめに
今日は、ロケールと言語およびタイムゾーンを日本仕様に設定する方法を学びたいと思います。過去に投稿した各環境では、明示的にその点を意識して設定したわけではないので、今回学習ついでに見直したいと思います。

# 環境の見直し

### Linuc学習環境
こちらの環境は過去にLinuc試験の学習用環境として構築したものです。ちなみに、無事Linucレベル1試験には合格しました。この時に作成した各種定義ファイルの内容と、今回修正した定義内容を下記に載せたいと思います。

```json:.devcontainer/devcontainer.json
{
    "name": "linuc",
    "dockerComposeFile": "../docker-compose.yml",
    "service": "pc",
    "workspaceFolder": "${localEnv:HOME}",
    "remoteUser": "${localEnv:USER}"
}
```

```diff_docker:build/pc/Dockerfile
FROM ubuntu:latest

ARG USER_UID
ARG USER_NAME
ARG GROUP_GID
ARG GROUP_NAME

RUN groupadd -g ${GROUP_GID} ${GROUP_NAME} \
  && useradd -m -s /bin/bash -u ${USER_UID} -g ${GROUP_GID} ${USER_NAME} \
  && apt-get update \
  && apt-get install -y sudo \
  && echo "${USER_NAME} ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/${USER_NAME} \
  && chmod 0440 /etc/sudoers.d/${USER_NAME}

+ RUN apt-get install -y language-pack-ja-base language-pack-ja locales
+ RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
+ ENV LANG ja_JP.UTF-8

+ RUN apt-get install -y tzdata \
+   && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

USER ${USER_NAME}
```

```text:.env
USER_UID={DockerホストOSの一般ユーザーのUID}
USER_NAME={DockerホストOSの一般ユーザーのユーザー名}
GROUP_GID={DockerホストOSの一般ユーザーのGID}
GROUP_NAME={DockerホストOSの一般ユーザーのグループ名}
```

```diff_yaml:docker-compose.yml
version: '3'
services:
  pc:
    build:
      context: ./build/pc/
      dockerfile: Dockerfile
      args:
        USER_UID: ${USER_UID}
        USER_NAME: ${USER_NAME}
        GROUP_GID: ${GROUP_GID}
        GROUP_NAME: ${GROUP_NAME}
    container_name: linuc_pc
    hostname: linuc_pc
    networks:
      - net
    tty: true
networks:
  net:
    name: linuc_net
```

注目すべきはDockerfileの変更内容です。
まず、この部分では、ロケールと言語の設定をしています。この環境で使用しているubuntoイメージは全く日本仕様になっていない素の状態なので、日本語化パックをインストールし、ロケールと言語を日本仕様に設定しています。

```Dockerfile:build/pc/Dockerfile
RUN apt-get install -y language-pack-ja-base language-pack-ja locales
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
```

次に、この部分では、タイムゾーンを日本仕様に設定しています。

```Dockerfile:build/pc/Dockerfile
RUN apt-get install -y tzdata \
  && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

それでは、コンテナをイメージから再作成して、変更前後で状況を見比べてみます。コンテナの再作成手順は、VSCodeでDocker Composeファイルを右クリックして、[Compose DOWN] → [Conpose UP]で行いました。やり方がご不明な方は、過去記事にたくさん載っていますので、そちらをご参照下さい。

```bash:コンテナ再作成前
hoge@linuc_pc:~$ locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
hoge@linuc_pc:~$ date
Sun May 22 03:00:32 UTC 2022
```

```bash:コンテナ再作成後
hoge@linuc_pc:~$ locale
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
hoge@linuc_pc:~$ date
2022年  5月 22日 日曜日 12:04:27 JST
```

うまくいきました。

### Blogテスト環境
こちらの環境は過去にBlog(WordPress)テスト用環境として構築したものです。この時に作成した各種定義ファイルの内容はこちらの過去記事をご参照下さい。

https://qiita.com/829yasubee/items/93ab15182f93b2689afa

以降では、変更した定義ファイルの内容のみ記載します。

```diff_docker:build/app/Dockerfile
FROM wordpress:latest

ARG USER_UID
ARG USER_NAME
ARG GROUP_GID
ARG GROUP_NAME

RUN groupadd -g ${GROUP_GID} ${GROUP_NAME} \
  && useradd -m -s /bin/bash -u ${USER_UID} -g ${GROUP_GID} ${USER_NAME} \
  && apt-get update \
  && apt-get install -y sudo \
  && echo "${USER_NAME} ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/${USER_NAME} \
  && chmod 0440 /etc/sudoers.d/${USER_NAME}

+ ENV LANG ja_JP.UTF-8

+ RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

USER ${USER_NAME}
```

```diff_docker:build/db/Dockerfile
FROM mysql:5.7

ARG USER_UID
ARG USER_NAME
ARG GROUP_GID
ARG GROUP_NAME

RUN groupadd -g ${GROUP_GID} ${GROUP_NAME} \
  && useradd -m -s /bin/bash -u ${USER_UID} -g ${GROUP_GID} ${USER_NAME} \
  && apt-get update \
  && apt-get install -y sudo \
  && echo "${USER_NAME} ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/${USER_NAME} \
  && chmod 0440 /etc/sudoers.d/${USER_NAME}

+ ENV LANG ja_JP.UTF-8

+ RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

この環境ではAPPサーバーとDBサーバー共に、ロケールと言語およびタイムゾーンの設定切り替えだけ行いました。日本語化パックやタイムゾーンのパッケージは既にインストール済みのイメージだった為。

それでは先程と同様に、コンテナをイメージから再作成して、環境が日本仕様に変わったか確認してみます。

```bash:コンテナ再作成後(APPサーバー)
hoge@blog_app:/var/www/html$ locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
hoge@blog_app:/var/www/html$ date
Sun May 22 13:11:35 JST 2022
```

```bash:コンテナ再作成後(DBサーバー)
root@blog_db:/# locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
root@blog_db:/# date
Sun May 22 13:14:00 JST 2022
```

うまくいきました。

### Laravel学習環境
こちらの環境は過去にLaravel学習用環境として構築したものです。この時に作成した各種定義ファイルの内容はこちらの過去記事をご参照下さい。

https://qiita.com/829yasubee/items/eddccb97d5d8d22ab743

以降では、変更した定義ファイルの内容のみ記載します。

```diff_docker:build/app/Dockerfile
FROM php:8.1-apache

ARG USER_UID
ARG USER_NAME
ARG GROUP_GID
ARG GROUP_NAME

RUN groupadd -g ${GROUP_GID} ${GROUP_NAME} \
  && useradd -m -s /bin/bash -u ${USER_UID} -g ${GROUP_GID} ${USER_NAME} \
  && apt-get update \
  && apt-get install -y sudo \
  && echo "${USER_NAME} ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/${USER_NAME} \
  && chmod 0440 /etc/sudoers.d/${USER_NAME}

+ ENV LANG ja_JP.UTF-8

+ RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

RUN apt-get update \
  && apt-get install -y git libpq-dev \
  && docker-php-ext-install pdo_pgsql

RUN pecl install xdebug \
  && docker-php-ext-enable xdebug

ADD 000-default.conf /etc/apache2/sites-available/
RUN a2enmod rewrite

USER ${USER_NAME}
```

```diff_docker:build/db/Dockerfile
FROM postgres:14.2

ARG USER_UID
ARG USER_NAME
ARG GROUP_GID
ARG GROUP_NAME

RUN groupadd -g ${GROUP_GID} ${GROUP_NAME} \
  && useradd -m -s /bin/bash -u ${USER_UID} -g ${GROUP_GID} ${USER_NAME} \
  && apt-get update \
  && apt-get install -y sudo \
  && echo "${USER_NAME} ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/${USER_NAME} \
  && chmod 0440 /etc/sudoers.d/${USER_NAME}

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

+ RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

```diff_yaml:docker-compose.yml
version: '3'
services:
  db:
    build:
      context: ./build/db/
      dockerfile: Dockerfile
      args:
        USER_UID: ${USER_UID}
        USER_NAME: ${USER_NAME}
        GROUP_GID: ${GROUP_GID}
        GROUP_NAME: ${GROUP_NAME}
    container_name: laravel_db
    hostname: laravel_db
    networks:
      - net
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
      - ./script/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    restart: always
    environment:
-     TZ: Asia/Tokyo
      POSTGRES_USER: ${DB_ROOT_USER}
      POSTGRES_PASSWORD: ${DB_ROOT_PASSWORD}
      POSTGRES_DB: ${DB_DATABASE}
      POSTGRES_NORMAL_USER: ${DB_USER}
      POSTGRES_NORMAL_PASSWORD: ${DB_PASSWORD}
  app:
    depends_on:
      - db
    build:
      context: ./build/app/
      dockerfile: Dockerfile
      args:
        USER_UID: ${USER_UID}
        USER_NAME: ${USER_NAME}
        GROUP_GID: ${GROUP_GID}
        GROUP_NAME: ${GROUP_NAME}
    container_name: laravel_app
    hostname: laravel_app
    networks:
      - net
    volumes:
      - ./data/app:/var/www/app
    ports:
      - ${APP_FORWARD_PORT}:80
    restart: always
-   environment:
-     TZ: Asia/Tokyo
  pgadmin:
    depends_on:
      - db
    image: dpage/pgadmin4:latest
    container_name: laravel_pgadmin
    hostname: laravel_pgadmin
    networks:
      - net
    volumes:
        - ./data/pgadmin:/var/lib/pgadmin
    ports:
        - ${DBTOOL_FORWARD_PORT}:80
    restart: always
    environment:
-     TZ: Asia/Tokyo
      PGADMIN_DEFAULT_EMAIL: ${DBTOOL_LOGIN_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${DBTOOL_LOGIN_PASSWORD}
networks:
  net:
    name: laravel_net
```

この環境に関して、APPサーバーでは、ロケールと言語およびタイムゾーンの設定切り替えだけ行いました。日本語化パックやタイムゾーンのパッケージは既にインストール済みのイメージだった為。
DBサーバーでは、タイムゾーンの設定切り替えだけ行いました。ロケールと言語の設定は定義済みであった為。また、この対応に伴い、docker-compose.ymlでタイムゾーン設定は不要になったので行わないようにしました。

それでは先程と同様に、コンテナをイメージから再作成して、環境が日本仕様に変わったか確認してみます。

```bash:コンテナ再作成後(APPサーバー)
hoge@laravel_app:/var/www/html$ locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
hoge@laravel_app:/var/www/html$ date
Sun May 22 14:13:44 JST 2022
```

```bash:コンテナ再作成後(DBサーバー)
root@laravel_db:/# locale
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
root@laravel_db:/# date
2022年  5月 22日 日曜日 14:14:48 JST
```

うまくいきました。

### Angular学習環境
こちらの環境は過去にAngular学習用環境として構築したものです。この時に作成した各種定義ファイルの内容はこちらの過去記事をご参照下さい。

https://qiita.com/829yasubee/items/ec1e87d4aa1ec231a60d

以降では、変更した定義ファイルの内容のみ記載します。

```diff_docker:build/web/Dockerfile
FROM ubuntu:latest

ARG USER_UID
ARG USER_NAME
ARG GROUP_GID
ARG GROUP_NAME

RUN groupadd -g ${GROUP_GID} ${GROUP_NAME} \
  && useradd -m -s /bin/bash -u ${USER_UID} -g ${GROUP_GID} ${USER_NAME} \
  && apt-get update \
  && apt-get install -y sudo \
  && echo "${USER_NAME} ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/${USER_NAME} \
  && chmod 0440 /etc/sudoers.d/${USER_NAME}

+ ENV LANG ja_JP.UTF-8

+ RUN apt-get install -y tzdata \
+   && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN apt-get update \
  && apt-get install -y curl git

RUN curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash - \
  && apt-get install -y nodejs \
  && npm install -g npm

RUN npm install -g @angular/cli

RUN cd /var \
  && mkdir www

USER ${USER_NAME}
```

```diff_yaml:docker-compose.yml
version: '3'
services:
  web:
    build:
      context: ./build/web/
      dockerfile: Dockerfile
      args:
        USER_UID: ${USER_UID}
        USER_NAME: ${USER_NAME}
        GROUP_GID: ${GROUP_GID}
        GROUP_NAME: ${GROUP_NAME}
    container_name: angular_web
    hostname: angular_web
    networks:
      - net
    volumes:
      - ./data/web:/var/www/html
    ports:
      - ${WEB_FORWARD_PORT}:4200
-   environment:
-     TZ: Asia/Tokyo
    tty: true
networks:
  net:
    name: angular_net
```

この環境では、ロケールと言語に関しては設定切り替えだけ、タイムゾーンに関しては、パッケージのインストールから行いました。また、この環境に関しても、この対応に伴い、docker-compose.ymlでタイムゾーン設定は不要になったので行わないようにしました。

それでは先程と同様に、コンテナをイメージから再作成して、環境が日本仕様に変わったか確認してみます。

```bash:コンテナ再作成後(WEBサーバー)
hoge@angular_web:/$ locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
hoge@angular_web:/$ date
Sun May 22 14:30:44 JST 2022
```

うまくいきました。

# 最後に
如何だったでしょうか。各環境でちょっとずつ必要な定義が異なりました。コンテナ生成で使用しているイメージファイルの状態によって、状況が異なるという事だと思います。その為、過去に構築した４つの環境に関して、全て変更点を掲載しました。環境に応じて、色々試行錯誤が必要ですね。
それでは、お疲れ様でした！