Node.js language-specific guide の備忘録

[Node.js language-specific guide](https://docs.docker.com/language/nodejs/) でハマった・ハマりそうな箇所のメモです。

## 環境
- Windows 10 Home
- Docker Desktop 4.30.0 (149282)
    - Docker version 26.1.1, build 4cf5afa
- https://github.com/docker/docker-nodejs-sample ([343b0ae](https://github.com/docker/docker-nodejs-sample/tree/343b0ae7434e74046fa3663ea5b0a7517fc6cc03))

## [Containerize a Node.js application](https://docs.docker.com/language/nodejs/containerize/)

### [Initialize Docker assets](https://docs.docker.com/language/nodejs/containerize/#initialize-docker-assets)

注意する点は起動するアプリケーションのパスがデフォルトの `index.js` でなく `src/index.js` なこと。

以下は <kbd>docker init</kbd> 利用時のログ。
<pre><samp>PS > <kbd>docker init</kbd>

Welcome to the Docker Init CLI!

This utility will walk you through creating the following files with sensible defaults for your project:
  - .dockerignore
  - Dockerfile
  - compose.yaml
  - README.Docker.md

Let's get started!

? What application platform does your project use? <kbd>Node</kbd>
? What version of Node do you want to use? <kbd>18.0.0</kbd>
       
? What version of Node do you want to use? 18.0.0
? Which package manager do you want to use? <kbd>npm</kbd>
? What command do you want to use to start the app? [tab for suggestions] (node index.js) <kbd>node <u>src/index.js</u></kbd>

? What command do you want to use to start the app? node src/index.js
? What port does your server listen on? <kbd>3000</kbd>

? What port does your server listen on? 3000

✔ Created → .dockerignore
✔ Created → Dockerfile
✔ Created → compose.yaml
✔ Created → README.Docker.md

→ Your Docker files are ready!
  Review your Docker files and tailor them to your application.
  Consult README.Docker.md for information about using the generated files.

What's next?
  Start your application by running → docker compose up --build
  Your application will be available at http://localhost:3000
</samp></pre>

## [Use containers for Node.js development](https://docs.docker.com/language/nodejs/develop/)

### [Add a local database and persist data](https://docs.docker.com/language/nodejs/develop/#add-a-local-database-and-persist-data)

#### 8. Open the password.txt file in an IDE or text editor, and specify a password of your choice. ...

`password.txt (db/password.txt)` にパスワード書いておしまい、と思っていたら以下のエラー発生。
<pre><samp>PS > <kbd>docker compose up --build</kbd>
...
db-1      | 
db-1      | PostgreSQL Database directory appears to contain a database; Skipping initialization
db-1      | 
db-1      | 2024-05-26 16:19:18.010 UTC [1] LOG:  starting PostgreSQL 16.3 (Debian 16.3-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
db-1      | 2024-05-26 16:19:18.011 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db-1      | 2024-05-26 16:19:18.011 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db-1      | 2024-05-26 16:19:18.042 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db-1      | 2024-05-26 16:19:18.080 UTC [51] LOG:  database system was shut down at 2024-05-26 16:19:17 UTC
db-1      | 2024-05-26 16:19:18.114 UTC [1] LOG:  database system is ready to accept connections
server-1  | Waiting for db:5432.
server-1  | Connected!
db-1      | <font style="color:red">2024-05-26 16:19:26.152 UTC [63] FATAL:  password authentication failed for user "postgres"</font>
db-1      | <font style="color:red">2024-05-26 16:19:26.152 UTC [63] DETAIL:  Connection matched file "/var/lib/postgresql/data/pg_hba.conf" line 128: "host all all all scram-sha-256"</font>
server-1  | <font style="color:red">Unable to connect to the database: error: password authentication failed for user "postgres"</font>
server-1  |     at Parser.parseErrorMessage (/usr/src/app/node_modules/pg-protocol/dist/parser.js:287:98)
server-1  |     at Parser.handlePacket (/usr/src/app/node_modules/pg-protocol/dist/parser.js:126:29)
server-1  |     at Parser.parse (/usr/src/app/node_modules/pg-protocol/dist/parser.js:39:38)
server-1  |     at Socket.&ltanonymous&gt (/usr/src/app/node_modules/pg-protocol/dist/index.js:11:42)
server-1  |     at Socket.emit (node:events:527:28)
server-1  |     at addChunk (node:internal/streams/readable:324:12)
server-1  |     at readableAddChunk (node:internal/streams/readable:297:9)
server-1  |     at Readable.push (node:internal/streams/readable:234:10)
server-1  |     at TCP.onStreamRead (node:internal/stream_base_commons:190:23) {
server-1  |   length: 104,
server-1  |   severity: 'FATAL',
server-1  |   code: '28P01',
server-1  |   detail: undefined,
server-1  |   hint: undefined,
server-1  |   position: undefined,
server-1  |   internalPosition: undefined,
server-1  |   internalQuery: undefined,
server-1  |   where: undefined,
server-1  |   schema: undefined,
server-1  |   table: undefined,
server-1  |   column: undefined,
server-1  |   dataType: undefined,
server-1  |   constraint: undefined,
server-1  |   file: 'auth.c',
server-1  |   line: '323',
server-1  |   routine: 'auth_failed'
server-1  | }
server-1  | Listening on port 3000
<samp></pre>

原因は `password.txt` の行末(パスワードの最後)に改行があったこと。
対応としては、行末に改行入れず、確実に1行で記載する。

もしエディタでファイル末尾に自動改行入れてる場合は解除すること。

VSCode だと以下設定を無効化しておく。
- テキストエディター (Text Editor)
    - ファイル (Files)
        - Insert Final Newline

settings.json では以下を消す。(2024/05/26時点の `files.insertFinalNewline` のデフォルト値は `false`)
```json
{
    ...
    "files.insertFinalNewline": true,
    ...
}
```

うまく行くと以下のログが出力される。
<pre><samp>PS > <kbd>docker compose up --build</kbd>
...
db-1      | 
db-1      | PostgreSQL Database directory appears to contain a database; Skipping initialization
db-1      | 
db-1      | 2024-05-26 16:54:17.076 UTC [1] LOG:  starting PostgreSQL 16.3 (Debian 16.3-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
db-1      | 2024-05-26 16:54:17.076 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db-1      | 2024-05-26 16:54:17.076 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db-1      | 2024-05-26 16:54:17.089 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db-1      | 2024-05-26 16:54:17.117 UTC [16] LOG:  database system was shut down at 2024-05-26 16:54:04 UTC
db-1      | 2024-05-26 16:54:17.161 UTC [1] LOG:  database system is ready to accept connections
server-1  | Waiting for db:5432.
server-1  | Connected!
server-1  | <font style="color:yellow">Connected to postgres db at host db</font>
server-1  | <font style="color:yellow">Connected to db and created table todo_items if it did not exist</font>
server-1  | Listening on port 3000
</samp></pre>

## [Test your Node.js deployment](https://docs.docker.com/language/nodejs/deploy/)

ひとつ前の [Configure CI/CD for your Node.js application](https://docs.docker.com/language/nodejs/configure-ci-cd/) で作成した自身のDocker Hub リポジトリからイメージを pull してくるが、この時点で自身のDocker Hub リポジトリをプライベートにしないこと。
パブリックのまま進めたほうがこの後が楽に進む。
このガイドを完走してからプライベートにするといい。

自身のDocker Hub リポジトリをプライベートにしたまま進める場合は Kubernetes にDocker Hubアカウントの認証情報を保存する必要がある。(らしい
- [Pull an Image from a Private Registry | Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/)

Windows 環境下(おそらく Docker Desktop) だと `credsStore` が `desktop` になっているので <kbd>kubectl create secret generic regcred</kbd> で `~/.docker/config.json` の中身が参照できない
- 参考設定
  <pre><samp>PS > <kbd>gc ${Env:\USERPROFILE}\.docker\config.json</kbd>
  {
         "auths": {
                 "https://index.docker.io/v1/": {}
         },
         "credsStore": "desktop",
         "currentContext": "default",
         "plugins": {
                 "-x-cli-hints": {
                         "enabled": "true"
                 }
         }
  }
  </samp></pre>

なので [Create a Secret by providing credentials on the command line](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-by-providing-credentials-on-the-command-line) に記載のコマンドで Kubernetes に Docker Hubアカウント情報を保存する。
らしいが、自身のDocker Hub リポジトリをプライベートにしたままだと、何故か認証できず・・・余裕があるときにリトライする。