구글 클라우드에서 운영중인 독푸딩 서비스가 있다. 도커를 모를 때라 서버에 필요한 프로그램을 한땀한땀 스크립트를 찾아가면서 설치를 했다. 오라클 클라우드로 API 서버와 DB서버를 이전하면서 도커를 이용했다. 도커만 설치되어 있다면 서버 프로그램을 간단히 실행하고 종료시킬 수 있게 되었다.
GCP 접속하여 Mongo 백업
# ssh 접속
dajkim76@Kims-Mac-mini ~/backend/gcp % ssh -i gcp.key 34.170.xxx.yyy
Enter passphrase for key 'gcp.key':
# mongo 백업
dajkim76@base-backend-1:~$ mongodump --db prod-db --out mongo_221122
# 폴더 압축
dajkim76@base-backend-1:~$ tar cvzf mongo_221122.tar.gz mongo_221122/
dajkim76@base-backend-1:~$ ls -al mongo_221122.tar.gz
-rw-rw-r-- 1 dajkim76 dajkim76 288717 Nov 21 15:45 mongo_221122.tar.gz
압축파일 가져오기
dajkim76@Kims-Mac-mini ~/backend/gcp % sftp -i gcp.key 34.170.xxx.yyy
Enter passphrase for key 'gcp.key':
Connected to 34.170.xxx.yyy.
sftp> get mongo_221122.tar.gz
Fetching /home/dajkim76/mongo_221122.tar.gz to mongo_221122.tar.gz
/home/dajkim76/mongo_221122.tar.gz 100% 282KB 280.5KB/s 00:01
sftp> exit
압축파일 오라클 vm에 업로드
dajkim76@Kims-Mac-mini ~/backend/oci % sftp -i oracle.key opc@132.145.xxx.yyy
Enter passphrase for key 'oracle.key':
Connected to 132.145.xxx.yyy.
sftp> put mongo_221122.tar.gz
Uploading mongo_221122.tar.gz to /home/opc/mongo_221122.tar.gz
mongo_221122.tar.gz 100% 282KB 2.8MB/s 00:00
sftp> exit
압축풀기
[opc@instance-20221029-2034 ~]$ tar xvzf mongo_221122.tar.gz
mongo 도커 컨테이너에 접속하여 db 복구하기
# 컨테이너 접속
docker exec -it docker_mongo_1 bash
# Mongo 복구: 호스트의 mongo_221122 디렉토리의 상위 폴더를 volumes에 바인딩시킬것
mongorestore -u root -p example ./mongo_221122
# 몽고 쉘 접속
mongosh -u root -p example
# 프로덕션 db에 유저 생성
use prod-db
db.createUser( { user: "prod-user", pwd: "prod-pwd", roles: [ { role: "readWrite", db: "prod-db" }, ] } )
이전에 오라클 클라우드에서 로드 밸런서에서 deno 웹 서버까지 연결 테스트 했다. mongo를 docker 켄테이너로 설치하고 deno 서버에서 mongo 서버로 connect까지 해 본다.
50GB volume을 /mnt/djkim 에 마운트했다.
이미 오라클 vm에 자체 block volume을 붙여놓았다. 50GB 용량을 가지고 있고, 이것은 어떤 VM에도 attach될 수 있다. 나중에 vm이 업그레이드 될 경우에도 block volume을 붙이면 데이타 그대로 유지된다. 현재는 mongo db의 저장소로 사용할 예정이다.
[opc@instance-20221029-2034 deno_service]$ docker-compose up -d
Starting deno_service_deno_1 ... done
[opc@instance-20221029-2034 deno_service]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eccd20973e1f mongo:6.0.2 "docker-entrypoint.s…" 19 minutes ago Up 18 minutes 0.0.0.0:27017->27017/tcp, :::27017->27017/tcp mongo_mongo_1
c9a0b542887a nginx:1.21.6 "/docker-entrypoint.…" 2 days ago Up 2 days 0.0.0.0:80->80/tcp, :::80->80/tcp nginx_nginx_1
42b92c017ed8 denoland/deno:1.28.0 "/tini -- docker-ent…" 2 days ago Up 12 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp deno_service_deno_1
[opc@instance-20221029-2034 deno_service]$ sudo docker logs --tail 10 deno_service_deno_1
Download https://deno.land/x/web_bson@v0.2.5/src/validate_utf8.ts
Download https://deno.land/x/web_bson@v0.2.5/src/float_parser.ts
Download https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/deps.ts
Download https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/load_code_points.ts
Download https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/sparse_bitfield.ts
Download https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/memory_pager.ts
mongodb connecting ...
mongodb connected OK
HTTP webserver running. Access it at: http://localhost:8080/
Listening on http://localhost:8080/
mongodb connected OK가 찍힌걸로 봐서 연결까지 된 듯 하다.
mongodb://root:example@mongo-host:27017 로 연결은 된 듯 하지만 실제로 읽기나 쓰기를 하면 auth 에러가 날 것이다. test-db에 권한이 없다고 나올 텐데 권한을 추가하자.. https://dajkim76.tistory.com/560 참고
[opc@instance-20221029-2034 deno_service]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eccd20973e1f mongo:6.0.2 "docker-entrypoint.s…" 46 minutes ago Up 46 minutes 0.0.0.0:27017->27017/tcp, :::27017->27017/tcp mongo_mongo_1
c9a0b542887a nginx:1.21.6 "/docker-entrypoint.…" 2 days ago Up 2 days 0.0.0.0:80->80/tcp, :::80->80/tcp nginx_nginx_1
42b92c017ed8 denoland/deno:1.28.0 "/tini -- docker-ent…" 2 days ago Up 27 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp deno_service_deno_1
[opc@instance-20221029-2034 deno_service]$ docker exec -it mongo_mongo_1 bash
root@mongo-host:/app# mongosh -u root -p example
Current Mongosh Log ID: 63765dee3755cc7187c2c247
Connecting to: mongodb://<credentials>@127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.6.0
Using MongoDB: 6.0.2
Using Mongosh: 1.6.0
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------
The server generated these startup warnings when booting
2022-11-17T15:25:14.257+00:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
2022-11-17T15:25:14.257+00:00: vm.max_map_count is too low
------
------
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).
The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
------
test> use test-db
switched to db test-db
test-db> db.createUser( { user: "testuser", pwd: "testpwd", roles: [ { role: "readWrite", db: "test-db" }, ] } )
{ ok: 1 }
test-db>
이제 mongodb://testuser:testpwd@mongo-host:27017 로 다시 연결을 만들고 read/write를 해보면 문제 없다. 테스트 해보지는 않았지만 아마도 될 듯.
테스트해 보자.. mongosh로 데이타를 하나 넣었다..
test> use test-db
switched to db test-db
test-db> db.user_list.insertOne({name:"name1", age:31})
{
acknowledged: true,
insertedId: ObjectId("63766d72b310e7e91006854b")
}
test-db>
실행 [opc@instance-20221029-2034 deno_service]$ docker-compose up -d Starting deno_service_deno_1 ... done
결과
dajkim76@Kims-Mac-mini ~ % curl https://oci.mdiwebma.com/deno-app
Your user-agent is:
[{"_id":"63766d72b310e7e91006854b","name":"name1","age":31}]
curl/7.79.1
https://oci.mdiwebma.com/deno-app. 누르면 오라클 클라우드 로드밸랜서 -> VM Nginx -> Deno app 서버 -> mongo db 순으로 요청 흐름이 발생하고 test-db의 user_list 콜렉션을 전부 가져와서 응답한다. nginx, deno, mongo는 모두 docker container로 동작한다.
dajkim76@Kims-Mac-mini ~ % curl https://oci.mdiwebma.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
연결 성공!!
F. 정리
최종 그림 User1... --->. OCI Load Balancer --> Backend_1 Nginx. --> WAS(Node or Deno) --> Backend_2 Nginx. --> WAS(Node or Deno)
-Nginx의 conf를 수정해서 서비스 혹은 App별로 WAS 인스턴스를 여러개 띄우면서 운영할 수 있을 듯.
roles에 db는 testdb로 저장되어 있지만 위에 db는 "test"로 저장되어 있는데 이게 문제 인듯하다. 위에 db는 createUser시에 파라미터로 넣을 수 없다. 넣으면 에러난다. 따라서 mongo-express에서 document를 "testdb"로 수정하니 인증 오류가 해결되었다. 왜 이런 문제가 생기는지는 잘 모르겠다. db이름에 끝에 db가 들어가서 문제가 되는듯..
2022/11/14일 추가 testdb를 선택하지 않아 생기는 문제였다. use testdb 하고 나서 createUser하면 정상적으로 유저가 등록된다...
test> use testdb
switched to db testdb
testdb> db.createUser( { user: "testuser_2", pwd: "testpwd_2", roles: [ { role: "readWrite", db: "testdb" }, ] } )
{ ok: 1 }
testdb>
import { Injectable } from '@nestjs/common';
import { User } from './db_models';
@Injectable()
export class AppService {
getHello(name: string): string {
const user = new User({ name: name });
user.save().then(() => console.log(name + ' saved'));
return 'Hello! ' + name;
}
}
auto increment 자체 구현
서버 db는 여러 유저의 데이타를 가지고 있는데, 유저마다 db를 생성할 수 없기 때문에, collection마다 이 documnet가 누구의 db인지를 구분할는 필드를 넣었다. 유저를 구분하는 용도로 did를 사용한다. cid는 collection별로 고정된 값을 가진다. 하나의 콜렉션에서 유저별로 서로 다른 고유하게 증가하는 sequence를 만들기 위한 테스트 작업이다.
import { Injectable } from '@nestjs/common';
import { User , getNextTs} from './db_models';
@Injectable()
export class AppService {
async getHello(name: string): Promise<string> {
const nextTs = await getNextTs(1, 1)
console.log("nextTs:" + nextTs)
const user = new User({ name: name, did: 1, ts: nextTs });
user.save().then(() => console.log(name + ' saved'));
return 'Hello! ' + name;
}
}
_id 대신에 Number 타입의 id를 쓰기. auto increment와 연계해서 만들 수는 있으나 _id 입력시 필드는 unique해야 한다
const userSchema = new mongoose.Schema({
// _id: ObjectId('6368d64ea66f9be19eee81c2'), 대신에 Number를 쓰겠다.
_id: {
type: Number
},
name: {
type :String,
},
did: {
type: Number,
},
ts: {
type: Number,
}
},{_id: false, //_id: ObjectId('6368d64ea66f9be19eee81c2'), 형태는 쓰지 않겠다.
collection:'user_list',
versionKey: false
});
_id는 그대로 두고, id를 새로 만든다. id는 중복가능하지만 did와 id의 조합은 unique하다. 이것을 createIndex 문으로 만들 수 있다. mongosh에서 db.id_list.createIndex( {cid: 1, did: 1}, { unique: true } ) db.user_list.createIndex({id: 1, did: 1}, { unique: true } )