개인 서버에서 Dokku를 운영하는 사례가 와일드카드 도메인 하나로 웹훅 수신기나 간단한 테스트 페이지 같은 임시 앱을 빠르게 만들고 삭제하는 방법을 소개한다. 앱별 DNS 설정과 인증서 발급 절차를 줄이고, 필요하면 SQLite 데이터를 배포 후에도 유지할 수 있다.
Dokku 서버에 *.apps.foo.tools를 가리키는 DNS 레코드를 추가하면, apps.foo.tools 아래의 각 호스트 이름으로 요청을 보낼 수 있다. Dokku의 nginx가 호스트 이름에 따라 요청을 앱으로 전달한다. 와일드카드 레코드는 자체 레코드가 없는 이름에만 적용되므로 서버의 다른 도메인에는 영향을 주지 않는다.
임시 앱 배포와 삭제
간단한 Node 앱은 package.json과 server.js 두 파일로 구성한다. 프레임워크나 의존성은 필요하지 않다. Node 빌드팩은 package.json을 확인하며, start 스크립트가 없으면 npm start가 node server.js를 실행한다.
package.json
{}
server.js
`require("http").createServer((req, res) => {
res.end("hello world from test-2\n");
}).listen(process.env.PORT || 5000);`
앱을 만들고 도메인을 지정한 뒤 저장소를 푸시하고 Let’s Encrypt를 활성화한다.
`dokku apps:create test-2
dokku domains:set test-2 test-2.apps.foo.tools
git push dokku@lab2:test-2 main
dokku letsencrypt:enable test-2`
사례에서는 약 25초 뒤 https://test-2.apps.foo.tools에서 자체 Let’s Encrypt 인증서와 함께 앱을 사용할 수 있었다. 앱을 삭제할 때는 다음 명령을 쓴다.
dokku apps:destroy test-2 --force
SQLite 데이터 유지
배포할 때마다 Dokku 컨테이너의 파일시스템은 폐기되므로 데이터베이스 파일을 호스트에 두고 컨테이너에 마운트해야 한다.
`dokku storage:ensure-directory test-3
dokku storage:mount test-3 /var/lib/dokku/data/storage/test-3:/data`
앱에서 /data/app.db를 읽고 쓰면 호스트의 /var/lib/dokku/data/storage/test-3/app.db에 데이터가 저장된다. 이 파일은 백업에도 활용할 수 있다.
사례에서는 SQLite가 내장된 Bun을 사용해 방문 횟수를 기록했다.
server.ts
``import { Database } from "bun:sqlite";
const db = new Database("/data/app.db", { create: true });
db.run("CREATE TABLE IF NOT EXISTS hits (at TEXT NOT NULL)");
Bun.serve({
port: process.env.PORT || 5000,
fetch() {
db.run("INSERT INTO hits VALUES (datetime('now'))");
const { n } = db.query("SELECT count(*) AS n FROM hits").get() as { n: number };
return new Response(hello from test-3, visit #${n}\n);
},
});``
Dockerfile은 다음과 같다.
Dockerfile
`FROM oven/bun:1-alpine
COPY server.ts /app/
CMD ["bun", "/app/server.ts"]`
EXPOSE를 생략하면 Dokku가 포트 80을 5000에 연결하므로 ports:set 단계가 필요하지 않다. dokku ps:rebuild를 실행한 뒤에도 방문 횟수는 이어졌다. 사례에서 사용한 이미지는 87 MB였고, 대기 상태 메모리 사용량은 4 MiB 미만으로 소개됐다.
알 수 없는 호스트 이름에 주의
와일드카드가 설정된 상태에서는 앱으로 등록되지 않은 typo.apps.foo.tools 같은 이름으로 들어온 요청도 서버에 도달한다. 기본 가상 호스트 설정이 없으면 nginx가 이를 기본 사이트로 전달할 수 있다. 사례의 서버에서는 nope.apps.foo.tools 요청이 실제 앱 중 하나를 인증서와 함께 표시했다.
이 사례에서는 내부 테스트용 앱이라 별도 조치를 하지 않았다. 알 수 없는 호스트 요청을 차단하려면 Dokku 문서에서 권장하는 기본 가상 호스트 설정을 적용할 수 있다.
`# /etc/nginx/conf.d/00-default-vhost.conf
server { listen 80 default_server; server_name _; return 444; }
server { listen 443 ssl default_server; server_name _; ssl_reject_handshake on; return 444; }`
글은 복잡한 개발 환경과 도구 체인에 비해 이런 방식이 간편하다며, Apache 서버에 PHP 파일을 FTP로 올리던 시절에 비유한다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요