コンテナからのインターネット制限(ドメインホワイトリスト)ですが、失敗しました。ホストのnftablesで開発コンテナからのリクエストであることを判別する方法が難しく、最後は開発コンテナを別のユーザーから立てることまでやったのだが、そうすると今度はファイルマウントの所有権がぐちゃぐちゃになってしまい、終わった。
ブラウザ上での動作確認を別の隔離コンテナに封じ込めることは簡単にできた。
# compose.yml
version: '3.8'
services:
app:
image: watch-duty-manager-app:latest
build:
context: .
dockerfile: ./ContainerFile
cap_drop:
- ALL
security_opt:
- no-new-privileges
pids_limit: 512
tmpfs:
- /tmp:rw,noexec,nosuid,nodev
- /var/tmp:rw,noexec,nosuid,nodev
environment:
- TZ=Asia/Tokyo
- NPM_CONFIG_IGNORE_SCRIPTS=true
- SSH_AUTH_SOCK=""
- SECRET=dummy
networks:
- dev-net
command: sleep infinity
volumes:
- ..:/workspaces:cached
browser:
image: kasmweb/chrome:1.14.0
ports:
- "6901:6901"
shm_size: '512m'
environment:
- VNC_PW=password
networks:
- dev-net
db:
container_name: watch-duty-manager-db-with-app
image: mysql:8.0.27
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: watch-duty-manager
MYSQL_USER: xxxx
MYSQL_PASSWORD: xxxx
volumes:
- db-data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
- ./mysql/log:/var/log/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
networks:
- dev-net
networks:
dev-net:
driver: bridge
volumes:
db-data:
# devcontainer.json
{
"name": "Node.js & TypeScript with Secure Browser",
"dockerComposeFile": "./compose.yml",
"service": "app",
"workspaceFolder": "/workspaces",
"postCreateCommand": "rm -rf /tmp/vscode-ssh-auth-* && npm ci --ignore-scripts",
"remoteUser": "node"
}
# vite.config.json
server: {
allowedHosts: ["app"],
host: true,
port: 5173,
https: {
key: fs.readFileSync("./.devcontainer/key.pem"),
cert: fs.readFileSync("./.devcontainer/cert.pem"),
},
hmr: { host: "app", protocol: "wss", clientPort: 5137 }
},
まず、devcontainerはcomposeもいける。それを使って開発用DBと動作確認用ブラウザコンテナを同時に立てる。動作確認用ブラウザコンテナはkasmweb/chromeを使うと、ホストからブラウザアクセスでコンテナ内でGUIでブラウザを操作でき、そのブラウザ内で https://app:5173 にアクセスすることで動作確認ができる。localhost以外からアプリケーションにアクセスするのでhost(0.0.0.0)が必要。httpsにしないとsecure付きcookieが死んでしまうので、鍵セットを自前で作ってappのvite.config.jsで読み込んでいる。