Docker コンテナにデプロイされた Django のタイムゾーンの問題

Docker コンテナにデプロイされた Django のタイムゾーンの問題

現在、コンテナ デプロイメントは非常に成熟しています。当社のサービスの多くはコンテナ デプロイメントを使用しており、更新とリカバリは非常に便利です。ただし、より厄介な問題があります。それは、タイム ゾーンの処理です。通常、これは TZ 環境変数を挿入することで解決されますが、この処理方法は Django では機能しません。

Django でのタイムゾーン設定

Django の設定ファイル settings.py には、時間とタイムゾーンに関連する TIME_ZONE と USE_TZ という 2 つの設定パラメータがあります。 settings.py で設定した後、Django はローカル時間を正しく取得できると期待していましたが、実際は期待に反しています。これら 2 つの設定が何をするのか見てみましょう。

USE_TZ=真

USE_TZ が True に設定されている場合、Django はシステムのデフォルトのタイムゾーンを使用します。このとき、TIME_ZONE 設定は基本的に無効であり、設定されているかどうかに関係なく効果はありません。

USE_TZ=偽

USE_TZがFalseに設定されている場合

  1. TIME_ZONEはNoneに設定されています
  2. Djangoはデフォルトのタイムゾーンを引き続き使用します
  3. TIME_ZONEが別のタイムゾーンに設定されている場合

Windows を使用している場合、TIME_ZONE 設定は役に立たず、Django はローカル時間を使用します。他のシステムを使用している場合は、そのタイムゾーンの UTC 時間を使用します。

たとえば、USE_TZ = False、TIME_ZONE = 'Asia/Shanghai' に設定すると、上海の UTC 時間が使用されます。

この時点では、時間は適切だと思うかもしれませんが、実際はそうではありません。システムのタイムゾーン設定にも注意する必要があります。

Linux コンテナでのタイムゾーンの設定

私の現地時間は16:15で、Djangoの設定はUSE_TZ = False、TIME_ZONE = 'Asia/Shanghai'です。

コンテナの時間とタイムゾーンを表示するためにコンテナに入るときに、TZ=Asia/Shanghai 環境変数を挿入しないでください。

システム時間はUTCタイムゾーンで表示され、時刻は08:15で、ちょうど8時間の差です。

Django環境に入り、時間とタイムゾーンを表示します。

python manage.py シェル 
 
datetime から datetime をインポート 
日付時刻.now() 
# 出力 datetime.datetime(2021, 10, 8, 8, 24, 8, 289230) 
 
django.utilsからタイムゾーンをインポートする 
タイムゾーン.get_current_timezone_name() 
# 'Asia/Shanghai' を出力

環境変数 TZ=Asia/Shanghai を挿入します
コンテナに入ると時間とタイムゾーンが表示されます

システム時間はアジアタイムゾーンで表示されますが、時間は実際の現地時間ではなく、UTC 時間のままです。

Django環境に入り、時間とタイムゾーンを表示します。

python manage.py シェル 
 
datetime から datetime をインポート 
日付時刻.now() 
# 出力 datetime.datetime(2021, 10, 8, 8, 24, 8, 289230) 
 
django.utilsからタイムゾーンをインポートする 
タイムゾーン.get_current_timezone_name() 
# 'Asia/Shanghai' を出力 

ご覧のとおり、タイムゾーンは変更されていますが、コンテナ自体とDjangoの両方で時刻はUTC時間のままです。

オンラインで検索すると、Linux システムのタイムゾーンを変更するには、/etc/localtime ファイルを変更する必要があることがわかります。

Linuxコンテナのタイムゾーンを変更する

通常は、ホストの /etc/localtime ファイルをコンテナの /etc/localtime ファイルにコピーします。しかし、クエリによって、/etc/localtime ファイルは実際には単なるソフト リンクであることがわかりました。実際のファイルは次のとおりです: /usr/share/zoneinfo/Asia/Shanghai

docker cp /usr/share/zoneinfo/Asia/Shanghai テスト:/etc/localtime
TZ=Asia/Shanghai 環境変数をコンテナに挿入せずにコンテナにログインすると、コンテナのシステム時刻がローカル時刻とタイムゾーンを正しく取得していることがわかります。

TZ=Asia/Shanghai 環境変数が挿入されている場合、/etc/localtime ファイルが置き換えられても、タイムゾーンのみが変更され、時間は UTC 時間のままです。

Django環境に入り、時間を表示します

python manage.py シェル 
 
datetime から datetime をインポート 
日付時刻.now() 
# 出力 datetime.datetime(2021, 10, 8, 8, 43, 43, 754698) 

Linux のシステム時間は正常ですが、Django 環境の時間は依然として不正確で、UTC 時間のままです。この時点で、多くの人が少し頭がおかしくなり、settings.py の USE_TZ と TIME_ZONE の設定に問題があると考えるかもしれません。実際には、問題はここにはありません。その理由は、datetime ライブラリは /usr/share/zoneinfo/ ディレクトリで Asia/Shanghai ファイルを検索しますが、イメージにはこのディレクトリが含まれていないため、Django は引き続き UTC タイムゾーンを使用するためです。解決策は非常に簡単です。/usr/share/zoneinfo/Asia ディレクトリを作成し、ファイルをこのディレクトリにコピーします。

# コンテナ内(このディレクトリが存在しない場合) 
mkdir -p /usr/share/zoneinfo/アジア 
 
# コンテナ外 docker cp /usr/share/zoneinfo/Asia/Shanghai test:/usr/share/zoneinfo/Asia/Shanghai

次にコンテナにログインし、Django環境に入り時間を確認します。

python manage.py シェル 
 
datetime から datetime をインポート 
日付時刻.now() 
# 出力 datetime.datetime(2021, 10, 8, 16, 49, 32, 57) 

今回はタイミングがぴったりでした。

要約する

コンテナのタイムゾーンの問題については、コンテナ作成フェーズで/etc/localtimeをインストールして設定することをお勧めします。たとえば、Dockerfileに次のステートメントを追加します。

/usr/share/zoneinfo/Asia/Shanghai を追加します。 /usr/share/zoneinfo/Asia/Shanghai 
 
RUN ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 

この方法では、コンテナを起動するときにタイムゾーンの問題を気にする必要はありません。コンテナが作成されている場合は、起動時にタイムゾーンファイルをマウントします。

docker run -d -v /etc/localtime:/etc/localtime -v /usr/share/zoneinfo/Asia/Shanghai:/usr/share/zoneinfo/Asia/Shanghai イメージ名 

この方法はもっと面倒です。私たちが現在直面しているもう 1 つの状況は、サービスがすでにオンラインになっていることです。時間的な問題があることがわかりました。2 つのファイルを手動でコンテナーにコピーし、コンテナーを再起動します。

docker cp /usr/share/zoneinfo/Asia/Shanghai テスト:/etc/localtime 
docker cp /usr/share/zoneinfo/Asia/Shanghai テスト:/usr/share/zoneinfo/Asia/Shanghai 
docker 再起動テスト 

これで、Docker コンテナに Django をデプロイする際のタイムゾーン問題についての記事は終了です。Django のタイムゾーンの Docker デプロイの詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Docker で Django アプリケーションをデプロイする例
  • docker を使用して Django テクノロジー スタック プロジェクトをデプロイする方法
  • Docker を使用して Django プロジェクトをデプロイする方法の例
  • Django Docker コンテナのデプロイ Django-Docker ローカルデプロイ
  • Python Django アプリケーションを Docker 化する方法
  • Docker-compose を使用して Django アプリケーションをオフラインでデプロイする方法
  • Dockerを使用してDjango+MySQL8開発環境をデプロイする方法の詳細な説明

<<:  CSS 使用のヒントのまとめ

>>:  CSSはコンテンツの高さが足りない場合にフッターを自動的に下部に固定します

推薦する

MySQL シリーズ 4 SQL 構文

目次チュートリアルシリーズ1. SQL言語の紹介と仕様2. データベース操作1. ライブラリを作成す...

IE6 の iframe の水平スクロール バーの解決策

状況は以下のとおりです: (PS: 赤いボックスは iframe 領域を表し、灰色の四角形は上記の ...

Docker、Nginx、Jenkins をベースにした自動フロントエンド デプロイメント

目次事前準備展開ターゲットDocker環境構築クラウドサーバーに接続Docker環境をインストールす...

Zabbix の psk 暗号化と zabbix_get 値の組み合わせ

Zabbix バージョン 3.0 以降、Zabbix サーバー、Zabbix プロキシ、Zabbix...

MySQLの制限を使用して大規模なページングの問題を解決する方法

序文日常の開発では、MySQL を使用してページングを実装する場合、常に MySQL 制限構文を使用...

MySQL の厄介な Aborted 警告をケーススタディで分析する

この記事では主に、MySQL の Aborted アラームに関する関連コンテンツを紹介し、参考と学習...

MySQL インデックスの失敗を引き起こす一般的な書き込み方法の概要

序文最近、古いプロジェクトから残ったいくつかの SQL 最適化の問題に対処するのに忙しくしています。...

Windows 10 での MySQL 5.7.17 のインストールと設定方法のグラフィック チュートリアル

この記事では、最新バージョンの MySQL データベース、つまり MySQL 5.7.17 圧縮バー...

Vue 親子コンポーネントの相互値の転送と呼び出し

目次1. 親が子コンポーネントに値を渡す2. 子コンポーネントが親コンポーネントに値を渡す3. 子コ...

CentOS の環境変数と設定ファイルの詳細な説明

序文CentOS 環境変数設定ファイル システムは階層型システムであり、他のマルチユーザー アプリケ...

Vue コンポーネント値転送中のデータ損失の分析と解決

序文前回の記事では、JavaScript の 2 つのデータ型、基本型と参照型、および参照型の浅いコ...

JavaScript で H5 ゴールド コイン関数を実装する (サンプル コード)

今日は春節の金貨の赤い封筒のアクティビティを作りました。なかなか良い出来だと思います。皆さんと共有し...

TypeScript における列挙型の理解と応用シナリオ

目次1. 何ですか2. 使用数値列挙文字列列挙異種列挙自然3. 応用シナリオ要約する1. 何ですか列...

this.parentNode.parentNode (親ノードの親ノード) はどういう意味ですか?

親ノードの親ノード、例えば、このような段落がありますHTML:コードをコピーコードは次のとおりです。...

無効と読み取り専用で入力を読み取り専用に設定する

読み取り専用入力を実現するには、無効と読み取り専用の 2 つの方法があります。当然、どちらの結果も読...