PHP7のDockerイメージをカスタマイズして使っていたら、apt updateでエラーになる

前提

以下のような、Dockerfileとcompose.ymlを使った環境がある

Dockerfile

FROM php:7.2.11-apache

# Install MySQL Extention
RUN docker-php-ext-install mysqli pdo_mysql

# Install GD Extention
RUN apt update && apt install -y \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libpng-dev \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) gd \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

compose.yml

services:
  server:
    build:
      context: .
    ports:
      - 80:80
    volumes:
      - ./src:/var/www/html
  db:
    image: mysql:5.7
    user: root
    secrets:
      - db-password
    volumes:
      - db-data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
      - MYSQL_DATABASE=example
    ports:
      - 3306:3306
volumes:
  db-data:
secrets:
  db-password:
    file: password.txt

ディレクトリ構成

$ tree
.
├── Dockerfile
├── compose.yml
├── password.txt
└── src
    └── index.php

状況

docker compose buildをすると

$ docker compose build
[+] Building 15.2s (6/6) FINISHED                                                                                                                                                                             docker:default
 => [server internal] load build definition from Dockerfile                                                                                                                                                             0.3s
 => => transferring dockerfile: 411B                                                                                                                                                                                    0.0s
 => [server internal] load .dockerignore                                                                                                                                                                                0.2s
 => => transferring context: 2B                                                                                                                                                                                         0.0s
 => [server internal] load metadata for docker.io/library/php:7.2.11-apache                                                                                                                                             0.0s
 => [server 1/3] FROM docker.io/library/php:7.2.11-apache                                                                                                                                                               0.0s
 => CACHED [server 2/3] RUN docker-php-ext-install mysqli pdo_mysql                                                                                                                                                     0.0s
 => ERROR [server 3/3] RUN apt-get update && apt-get install -y     libfreetype6-dev     libjpeg62-turbo-dev     libpng-dev     && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr  13.6s
------
 > [server 3/3] RUN apt-get update && apt-get install -y     libfreetype6-dev     libjpeg62-turbo-dev     libpng-dev     && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/     && docker-php-ext-install -j$(nproc) gd:
1.330 Ign:1 http://security.debian.org/debian-security stretch/updates InRelease
1.589 Ign:2 http://deb.debian.org/debian stretch InRelease
:
:
:
3.902 Err:8 http://security.debian.org/debian-security stretch/updates/main amd64 Packages
3.902   404  Not Found [IP: 151.101.194.132 80]
:
:
:
11.67 Err:16 http://deb.debian.org/debian stretch/main amd64 Packages
11.67   404  Not Found
:
12.54 Err:18 http://deb.debian.org/debian stretch-updates/main amd64 Packages
12.54   404  Not Found
12.55 Fetched 8706 kB in 11s (772 kB/s)
12.55 Reading package lists...
13.01 W: The repository 'http://security.debian.org/debian-security stretch/updates Release' does not have a Release file.
13.01 W: GPG error: http://security.debian.org/debian-security buster/updates InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 112695A0E562B32A NO_PUBKEY 54404762BBB6E853
13.01 W: The repository 'http://security.debian.org/debian-security buster/updates InRelease' is not signed.
13.01 W: GPG error: http://deb.debian.org/debian buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY DCC9EFBF77E11517
13.01 W: The repository 'http://deb.debian.org/debian buster InRelease' is not signed.
13.01 W: GPG error: http://deb.debian.org/debian buster-updates InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D386FA1D9
13.01 W: The repository 'http://deb.debian.org/debian buster-updates InRelease' is not signed.
13.01 W: The repository 'http://deb.debian.org/debian stretch Release' does not have a Release file.
13.01 W: The repository 'http://deb.debian.org/debian stretch-updates Release' does not have a Release file.
13.01 E: Failed to fetch http://security.debian.org/debian-security/dists/stretch/updates/main/binary-amd64/Packages  404  Not Found [IP: 151.101.194.132 80]
13.01 E: Failed to fetch http://deb.debian.org/debian/dists/stretch/main/binary-amd64/Packages  404  Not Found
13.01 E: Failed to fetch http://deb.debian.org/debian/dists/stretch-updates/main/binary-amd64/Packages  404  Not Found
13.01 E: Some index files failed to download. They have been ignored, or old ones used instead.
------
failed to solve: process "/bin/sh -c apt-get update && apt-get install -y     libfreetype6-dev     libjpeg62-turbo-dev     libpng-dev     && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/     && docker-php-ext-install -j$(nproc) gd" did not complete successfully: exit code: 100

エラー内容から http://deb.debian.org/debian にアクセスすると、dists以下にstretchが見つからない。

【Debianサポート終了】Google Cloud RunにDockerfileを使ってデプロイしようとしたらエラーが出た によると、Debian 9.0(stretch)のサポートが2022年6月30日で終了したため、パッケージリポジトリは http://archive.debian.org に移動したとのこと。

そのため、Dockerfile内でapt updateをすると、エラーとなってしまっていた。

そこで、PHPイメージ内の/etc/apt/source.listにあるURLを書き換える。

対応

書き換え前

# cat /etc/apt/sources.list
deb http://deb.debian.org/debian stretch main
deb http://security.debian.org/debian-security stretch/updates main
deb http://deb.debian.org/debian stretch-updates main

http://deb.debian.org , http://security.debian.orghttp://archive.debian.org に変更する。 また、スイートのstretch-updatesはなくなったため削除する。

sed -i -e 's#deb.debian.org#archive.debian.org#' -e 's#security.debian.org#archive.debian.org#' -e '/stretch-updates/d' /etc/apt/sources.list

この状態でapt udpateを実行すると、/etc/apt/sources.list.d/buster.listNO_PUBKEY エラーが発生する。

# apt update
Get:1 http://deb.debian.org/debian buster InRelease [122 kB]
Err:1 http://deb.debian.org/debian buster InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY DCC9EFBF77E11517
Get:2 http://deb.debian.org/debian buster-updates InRelease [56.6 kB]
Err:2 http://deb.debian.org/debian buster-updates InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D386FA1D9
Get:3 http://security.debian.org/debian-security buster/updates InRelease [34.8 kB]
Err:3 http://security.debian.org/debian-security buster/updates InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 112695A0E562B32A NO_PUBKEY 54404762BBB6E853
Ign:4 http://archive.debian.org/debian stretch InRelease
Get:5 http://archive.debian.org/debian-security stretch/updates InRelease [59.1 kB]
Get:6 http://archive.debian.org/debian stretch Release [118 kB]
Get:7 http://archive.debian.org/debian stretch Release.gpg [3177 B]
Get:8 http://archive.debian.org/debian-security stretch/updates/main amd64 Packages [782 kB]
Get:9 http://archive.debian.org/debian stretch/main amd64 Packages [7080 kB]
Reading package lists... Done
W: GPG error: http://deb.debian.org/debian buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY DCC9EFBF77E11517
E: The repository 'http://deb.debian.org/debian buster InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
W: GPG error: http://deb.debian.org/debian buster-updates InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D386FA1D9
E: The repository 'http://deb.debian.org/debian buster-updates InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
W: GPG error: http://security.debian.org/debian-security buster/updates InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 112695A0E562B32A NO_PUBKEY 54404762BBB6E853
E: The repository 'http://security.debian.org/debian-security buster/updates InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.

/etc/apt/sources.list.d/buster.listを削除しても今回の場合問題ないが、そのままにしておく場合、debian-archive-keyringをインストールする

# apt update
# apt install -y debian-archive-keyring 

apt updateもすべて成功する

# apt update
Get:1 http://security.debian.org/debian-security buster/updates InRelease [34.8 kB]
:
:
:
Reading package lists... Done
Building dependency tree
Reading state information... Done
71 packages can be upgraded. Run 'apt list --upgradable' to see them.

最終的なDockerfileは

  • /etc/apt/sources.list.d/buster.listをなくした場合
@@ -1,5 +1,8 @@
 FROM php:7.2.11-apache

+RUN sed -i -e 's#deb.debian.org#archive.debian.org#' -e 's#security.debian.org#archive.debian.org#' -e '/stretch-updates/d' /etc/apt/sources.list \
+    && rm /etc/apt/sources.list.d/buster.list
+
 # Install MySQL Extention
 RUN docker-php-ext-install mysqli pdo_mysql
  • /etc/apt/sources.list.d/buster.listを残す場合
@@ -1,5 +1,13 @@
 FROM php:7.2.11-apache

+RUN sed -i -e 's#deb.debian.org#archive.debian.org#' -e 's#security.debian.org#archive.debian.org#' -e '/stretch-updates/d' /etc/apt/sources.list \
+    && mv /etc/apt/sources.list.d/buster.list /etc/apt/sources.list.d/buster.list.disabled \
+    && apt update \
+    && apt install -y debian-archive-keyring \
+    && mv /etc/apt/sources.list.d/buster.list.disabled /etc/apt/sources.list.d/buster.list \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
 # Install MySQL Extention
 RUN docker-php-ext-install mysqli pdo_mysql

debian stretchを使っていることを明確にするためにベースイメージをphp:7.2.11-apache-stretch変更しても可能でした

参考

Nuxt3のuseFetch()のパラメータにcomputedやrefの値を用いると、それらが変更されるたびにリクエストが行われる

useFetch automatic request after first request · Issue #15741 · nuxt/nuxt より

動作検証サンプル ( https://github.com/nuxt/nuxt/issues/15741#issuecomment-1397417760 ) より

<script setup>
const formData = reactive({
  username: "",
  password: "",
  confirmPassword: null,
});

const handleSubmit = async () => {
  console.log("Running handleSubmit...");
  const response = await useFetch("/api/register", {
    method: "POST",
    body: formData,
  });
};
</script>

<template>
  <div>
    <h2>Register</h2>
    <form @submit.prevent="handleSubmit">
      <div>
        <label>Username</label>
        <input v-model="formData.username" type="text" />
      </div>
      :
      :
      :
      :
      <div class="pt-2">
        <button type="submit"> Register </button>
      </div>
    </form>
  </div>
</template>
  1. 各項目を入力する
  2. Registerボタンを押すとhandleSubmit()が実行され、/api/registerへPOSTリクエストが発行される
  3. input要素の内容を書き換えると、書き換えるたびに2.のPOSTリクエストが発生する。送信されるパラメータは書き換えた最新の値

リクエストサンプル

これは、Nuxt3のドキュメントに書かれている、正常な動作である。

useFetch · Nuxt Composables

All fetch options can be given a computed or ref value. These will be watched and new requests made automatically with any new values if they are updated.

すべてのfetchオプションは、computedまたはrefを与えることができます。これらは監視され、新しい値に更新された場合は自動的に新しいリクエストが行われます。

これを回避したいときは、

  1. パラメータにref/reativeをそのまま用いるのをやめる

      const response = await useFetch("/api/register", {
        method: "POST",
        body: JSON.stringify(formData),
      });
      
      または
      
      const response = await useFetch("/api/register", {
        method: "POST",
        body: {...formData},
      });
    
      または
      
      const response = await useFetch("/api/register", {
        method: "POST",
        body: formData.value,
      });
    
  2. useFetchの代わりに$fetchを用いる

      const response = await $fetch("/api/register", {
        method: "POST",
        body: formData,
      });
    

Let’s EncryptのSSL証明書の有効期限一覧を出力

ドメイン名と証明書の有効期限を確認したかったので、certbot certificatesで証明書の一覧が出力されるのを利用して、grepとsedで必要なフィールドを取り出す

コマンド

sudo certbot certificates 2> /dev/null | grep -A 4 "Certificate Name" | sed -n -e '/Certificate/p;/Domains/p;/Expiry/p'

certbot部

certbot certificatesだけだとエラー出力に Saving debug log to /var/log/letsencrypt/letsencrypt.log が出力されてしまうので、それを/dev/nullに捨てている

grep部

Certificate Nameを含む行から数えて、Expiry Dateがある4行目までを抽出

sed部

"Certificate Name", "Domains", "Expiry Date"でマッチした行のみを出力

実行サンプル

$ sudo certbot certificates 2> /dev/null | grep -A 4 "Certificate Name" | sed -n -e '/Certificate Name/p;/Domains/p;/Expiry Date/p'
  Certificate Name: example.com
    Domains: example.com sub1.example.com sub2.example.com
    Expiry Date: 2023-05-10 05:35:12+00:00 (VALID: 69 days)
  Certificate Name: sub3.example.com
    Domains: sub3.example.com
    Expiry Date: 2023-04-16 03:16:55+00:00 (VALID: 44 days)
  Certificate Name: sub4.example.com
    Domains: sub4.example.com
    Expiry Date: 2023-05-10 05:35:18+00:00 (VALID: 69 days)

※grep部分は省略しても同じ結果でした

$ sudo certbot certificates 2> /dev/null | sed -n -e '/Certificate Name/p;/Domains/p;/Expiry Date/p'

参考

オープンソース ERP の iDempiere の日本商習慣対応ディストリビューション JPiere9 を Docker Compose で動かす

オープンソースの ERP iDempiere のDocker 版の Docker Compose のサンプルからJPiere9を動かしてみる。

ファイル

  • Dockerfile
  • compose.yml
version: "3.7"
services:
idempiere:
build: .
volumes:
- idempiere_config:/opt/idempiere/configuration
- idempiere_plugins:/opt/idempiere/plugins
environment:
- TZ=Asia/Tokyo
ports:
- 8080:8080
- 8443:8443
- 12612:12612
depends_on:
- postgres
postgres:
image: postgres:12
volumes:
- idempiere_data:/var/lib/postgresql/data
environment:
- TZ=Asia/Tokyo
- POSTGRES_PASSWORD=postgres
ports:
- 5432:5432
volumes:
idempiere_data:
idempiere_plugins:
idempiere_config:
view raw compose.yml hosted with ❤ by GitHub
FROM idempiereofficial/idempiere:9
# JPiere9のインストールパッケージ
ENV JPIERE_BUILD https://osdn.net/frs/redir.php?m=nchc&f=jpiere%2F77250%2FJPiereServer9.Linux.x86_64.zip
# JPiere9のダンプファイル
ENV JPIERE_DUMPFILE https://osdn.net/frs/redir.php?m=rwthaachen&f=jpiere%2F77250%2FExpDat.jar
# JPiere9のインストールパッケージをダウンロードして既存のiDempiereと置き換える
RUN wget -q --no-check-certificate "$JPIERE_BUILD" -O /tmp/JPiereServer9.Linux.x86_64.zip && \
echo "Hash: $(md5sum /tmp/JPiereServer9.Linux.x86_64.zip)" > "$IDEMPIERE_HOME/MD5SUMS" && \
echo "Date: $(date)" >> "$IDEMPIERE_HOME/MD5SUMS" && \
unzip -q -o /tmp/JPiereServer9.Linux.x86_64.zip -d /opt && \
# 元のDockerfileでコピーされたファイルをJPiere側に移す
cp "$IDEMPIERE_HOME/docker-entrypoint.sh" /opt/jpiere-server && \
cp "$IDEMPIERE_HOME/idempiere-server.sh" /opt/jpiere-server && \
cp "$IDEMPIERE_HOME/MD5SUMS" /opt/jpiere-server && \
# 置き換え
rm -rf "$IDEMPIERE_HOME" && mv /opt/jpiere-server "$IDEMPIERE_HOME" && \
# シェルスクリプトの改行コードをLFにし、実行権限を付加
find "$IDEMPIERE_HOME" -name "*.sh" -exec sed -i -e 's/\r//g' {} \; && \
find "$IDEMPIERE_HOME" -name "*.sh" -exec chmod +x {} \; && \
chmod 777 "$IDEMPIERE_HOME/idempiere" && \
# ダウンロードファイル削除
rm -f /tmp/JPiereServer9.Linux.x86_64.zip
# JPiere9のダンプファイルをダウンロードし、DBインポートスクリプト内でJPiere9のダンプファイルをインポートするようにする
RUN wget -q --no-check-certificate "$JPIERE_DUMPFILE" -O "$IDEMPIERE_HOME/data/seed/ExpDat.jar" && \
sed -i -e "s#jar xvf Adempiere\${SUFFIX}.jar#jar xvf ExpDat.jar\nmv \$IDEMPIERE_HOME/data/seed/ExpDat.dmp \$IDEMPIERE_HOME/data/seed/Adempiere\${SUFFIX}.dmp#" \
"$IDEMPIERE_HOME/utils/RUN_ImportIdempiere.sh"
view raw Dockerfile hosted with ❤ by GitHub

イメージを作成して、コンテナ起動

docker compose build
docker compose up

ブラウザから https://localhost:8443/webui/ でアクセス

ユーザー(メールアドレス)とパスワードはJPiere9 のインストール – OSS ERP Compiere Distribution Labから

コンテナ初回起動時、先に PostgreSQL が起動し終える前に、後続の JPiere の DB インポートが行なわれた場合、インストールが失敗するので、その際は分けて起動する

docker compose up postgres -d
# 起動完了を待つ(docker compose logs -f postgresなどで) 
docker compose up

参考