# Build and Deploy Document - เอกสารนี้เป็นเอกสารสำหรับให้ Developer ดูขั้นตอนการ Deploy ในส่วนของ Test Server และ Production Server สำหรับระบบ BMA eHR ## TEST Environment 1. Environment Diagram ![รูปภาพที่ 1 - 1 ](images/buildanddeploy/build1-1.png#center) 2. หลักการทำงานของระบบ เมื่อมีการ Request มาจากหน้าเว็บ request ทั้งหมดจะถูกส่งมาที่ Traefik ที่เป็นตัว API Gateway โดยที่ตัว Traefik จะดูจาก Rule ที่เราได้ทำการตั้งค่าเอาไว้ที่ docker-compose.yml ว่าเมื่อมีการ Request เข้ามาที่ Url Path ไหนจะทำการ Point ไปที่ Docker Container ตัวใด โดยที่ก่อนใช้งานระบบ จะต้องทำการ Authentication โดยผ่าน Keycloak ซึ่งเมื่อผ่านแล้วจึงจะสามารถใช้งานระบบได้ และเมื่อมีการเรียกใช้งาน API นั้น ตัว API จะทำการ Validate Access Token ที่แนบมากับ Request ทุกครั้งว่า valid หรือไม่ หลังจากนั้น API จะทำการ Query Database ตาม Logic ของ Application แล้วหลังจากนั้น จึงส่งผลลัพธ์กลับไปให้ FrontEnd แสดงผล 3. เครื่องที่ใช้สำหรับการทดสอบระบบจะติดตั้งอยู่ที่เครื่อง **192.168.1.9** โดยหากเป็นการติดตั้ง Service ที่พัฒนาขึ้นมาใหม่โดยที่ยังไม่เคยทำการติดตั้งมาก่อน จะต้องทำการสร้าง folder สำหรับติดตั้งที่ Server ก่อน ซึ่งการจะเข้าสู่ Server จะต้องทำการ Secure Shell เพื่อเข้าไปยังเครื่อง server โดยใช้คำสั่ง ```bash ssh frappet@frappet.com ``` - หลังจากนั้นให้ใส่รหัสผ่าน ==“FPTadmin2357”== 4. เมื่อเข้าสู่ server ให้ Chage directory ไปที่ folder /home/docker โดยใช้คำสั่ง ```bash cd docker ``` 5. หากต้องการจะดูว่าใน folder นี้มี sub folder อะไรบ้างใช้คำสั่ง ```bash ls -la ``` - หรือ ```bash ls ``` 6. หลังจากนั้นสร้าง folder ของ service เช่นหากต้องการสร้าง service ของระบบงาน report ให้ทำการสร้าง folder โดยใช้คำสั่งดังนี้ ```bash mkdir bma-ehr-{service name} ``` - โดยเปลี่ยน service name เป็นชื่อ service ของตัวเอง เพื่อให้สามารถจำแนกได้ว่า folder นี้เป็น service อะไรของระบบ bma-ehr 7. ทำการสร้างไฟล์ docker-compose.yml ตามโค้ดตัวอย่าง ```yaml version: "3.4" services: bma-ehr-report-v2: image: docker.frappet.com/ehr/bma-ehr-report-v2-service:latest # image: docker.frappet.com/ehr/bma-ehr-report:test-v2 restart: unless-stopped ports: - "6029:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings.json:/app/appsettings.json - ./appsettings.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-api-report-v2.rule=Host(`bma-ehr.frappet.synology.me`) && PathPrefix(`/api/v2/report`)" networks: - bma-ehr networks: bma-ehr: external: true ``` 8. โดยทำการเปลี่ยนชื่อ Service เป็นชื่อของ docker image service ที่เราจะต้องทำการ push ขึ้น docker registry ของบริษัท 9. เปลี่ยน Port ของ Host **โดย ห้ามซ้ำกับของ Service อื่นๆ** 10. เปลี่ยน Label ในส่วนของชื่อ rule ของ traefik โดยห้ามซ้ำกัน เพราะจะทำให้ Traefik สับสนได้ หลังจากนั้นแก้ URL และ PathPrefix ให้ตรงกับ Path ของตัว API ของเรา 11. สร้าง folder wwwroot เพื่อว่าจะมีการใช้งาน static file 12. สร้าง file appsettings.json เพื่อทำการตั้งค่า config ต่างๆของตัว api ที่จะให้ test env นั้น ต่อฐานข้อมูลไปที่ server ไหน ตามตัวอย่าง **ค่า config ต่างๆอาจจะเปลี่ยนไปตามแต่ละ Service ดังนั้นให้ดูจาก Code ที่ตัวเองเขียนว่ามีการใช้ค่า Config อะไรบ้าง** ```json { "Serilog": { "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Information", "System": "Warning" } } }, "ElasticConfiguration": { "Uri": "http://localhost:9200" }, "AllowedHosts": "*", "ConnectionStrings": { "MongoConnection": "mongodb://admin:adminVM123@bma-mongodb-test1:27017", "DefaultConnection": "server=bma-mysql-test1;user=root;password=adminVM123;database=bma_ehr;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;" }, "Jwt": { "Key": "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI", "Issuer": "https://id.frappet.synology.me/realms/bma-ehr" }, "EPPlus": { "ExcelPackage": { "LicenseContext": "NonCommercial" } }, "MinIO": { "Endpoint": "https://s3cluster.frappet.com/", "AccessKey": "frappet", "SecretKey": "FPTadmin2357", "BucketName": "bma-ehr-fpt" }, "Node": { "API": "https://bma-ehr.frappet.com/api/v1/probation" }, "Mail": { "Server": "smtp.gmail.com", "User": "suphonchai.ph@gmail.com", "Password": "nnjazjcnwhepkxdm", "MailFrom": "suphonchai.ph@gmail.com", "Port": "587" }, "Protocol": "HTTPS", "API": "https://bma-ehr.frappet.com/api/v1" } ``` 13. หลังจากนั้นให้ทำการสร้าง Dockerfile ไว้ที่ Folder ของ Sourcecode ของ Service ที่เราทำการพัฒนาตามตัวอย่างนี้ โดยแก้ไขค่าให้สอดคล้องกันกับตัวระบบที่เราพัฒนา ```json FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY ["BMA.EHR.Domain/BMA.EHR.Domain.csproj", "BMA.EHR.Domain/"] COPY ["BMA.EHR.Application/BMA.EHR.Application.csproj", "BMA.EHR.Application/"] COPY ["BMA.EHR.Infrastructure/BMA.EHR.Infrastructure.csproj", "BMA.EHR.Infrastructure/"] COPY ["BMA.EHR.Report.Service/BMA.EHR.Report.Service.csproj", "BMA.EHR.Report.Service/"] COPY ./BMA.EHR.Report.Service/Components ./BMA.EHR.Report.Service/Components COPY ./BMA.EHR.Report.Service/nuget.config ./BMA.EHR.Report.Service/ RUN dotnet restore "BMA.EHR.Report.Service/BMA.EHR.Report.Service.csproj" COPY . . WORKDIR "/src/BMA.EHR.Report.Service" RUN dotnet build "BMA.EHR.Report.Service.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "BMA.EHR.Report.Service.csproj" -c Release -o /app/publish /p:UseAppHost=false FROM base AS final RUN apt-get update && apt-get -y install fontconfig && apt-get install -y --allow-unauthenticated libgdiplus libc6-dev libx11-dev && rm -rf /var/lib/apt/lists/* COPY ./BMA.EHR.Report.Service/Fonts/THSarabunIT.ttf /usr/share/fonts/truetype/ COPY ./BMA.EHR.Report.Service/Fonts/THSarabunITBold.ttf /usr/share/fonts/truetype/ COPY ./BMA.EHR.Report.Service/Fonts/THSarabunITItalic.ttf /usr/share/fonts/truetype/ COPY ./BMA.EHR.Report.Service/Fonts/THSarabunITBoldItalic.ttf /usr/share/fonts/truetype/ COPY ./BMA.EHR.Report.Service/Fonts/THSarabunNew.ttf /usr/share/fonts/truetype/ COPY ./BMA.EHR.Report.Service/Fonts/THSarabunNewBold.ttf /usr/share/fonts/truetype/ COPY ./BMA.EHR.Report.Service/Fonts/THSarabunNewItalic.ttf /usr/share/fonts/truetype/ COPY ./BMA.EHR.Report.Service/Fonts/THSarabunNewBoldItalic.ttf /usr/share/fonts/truetype/ RUN fc-cache -f -v WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "BMA.EHR.Report.Service.dll"] ``` 14. โดยที่ Dockerfile นี้จะเป็นไฟล์สำคัญที่เราจะใช้ในการ build docker image 15. ทำการสร้างไฟล์ GitHub Action Script โดยดูตัวอย่างได้ จาก Folder ใน Sourcecode ![รูปภาพที่ 1 - 2 ](images/buildanddeploy/build1-2.png#center) 16. โดยทำการสร้างไฟล์ release\_{service name}.yaml เพื่อทำการ Build and Deploy ของ Service ที่พัฒนาเพิ่ม ตามตัวอย่าง โดยทำการแก้ไขค่า folder และไฟล์ต่างๆให้ถูกต้องกับ Service ที่กำลังพัฒนา ```yaml name: release-dev run-name: release-dev ${{ github.actor }} on: # push: # tags: # - 'v[0-9]+.[0-9]+.[0-9]+' # tags-ignore: # - '2.*' # Allow run workflow manually from Action tab workflow_dispatch: env: REGISTRY: docker.frappet.com IMAGE_NAME: ehr/bma-ehr-report-v2-service DEPLOY_HOST: frappet.com COMPOSE_PATH: /home/frappet/docker/bma-ehr-report-v2 TOKEN_LINE: uxuK5hDzS2DsoC5piJBrWRLiz8GgY7iMZZldOWsDDF0 jobs: # act workflow_dispatch -W .github/workflows/release_report.yaml --input IMAGE_VER=test-v6.1 -s DOCKER_USER=sorawit -s DOCKER_PASS=P@ssword -s SSH_PASSWORD=P@ssw0rd release-dev: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 # skip Set up QEMU because it fail on act and container - name: Gen Version id: gen_ver run: | if [[ $GITHUB_REF == 'refs/tags/'* ]]; then IMAGE_VER='${GITHUB_REF/refs\/tags\//}' else IMAGE_VER=${{ github.event.inputs.IMAGE_VER }} fi if [[ $IMAGE_VER == '' ]]; then IMAGE_VER='test-vBeta' fi echo '::set-output name=image_ver::'$IMAGE_VER - name: Test Version run: | echo $GITHUB_REF echo ${{ steps.gen_ver.outputs.image_ver }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login in to registry uses: docker/login-action@v2 with: registry: ${{env.REGISTRY}} username: ${{secrets.DOCKER_USER}} password: ${{secrets.DOCKER_PASS}} - name: Build and load local docker image uses: docker/build-push-action@v3 with: context: . platforms: linux/amd64 file: BMA.EHR.Report.Service/Dockerfile push: true tags: ${{env.REGISTRY}}/${{env.IMAGE_NAME}}:${{ steps.gen_ver.outputs.image_ver }},${{env.REGISTRY}}/${{env.IMAGE_NAME}}:latest - name: Reload docker compose uses: appleboy/ssh-action@v0.1.8 with: host: ${{env.DEPLOY_HOST}} username: frappet password: ${{ secrets.SSH_PASSWORD }} port: 22 script: | cd "${{env.COMPOSE_PATH}}" docker-compose pull docker-compose up -d echo "${{ steps.gen_ver.outputs.image_ver }}"> success - uses: snow-actions/line-notify@v1.1.0 if: success() with: access_token: ${{ env.TOKEN_LINE }} message: | -Success✅✅✅ Image: ${{env.IMAGE_NAME}} Version: ${{ github.event.inputs.IMAGE_VER }} By: ${{secrets.DOCKER_USER}} - uses: snow-actions/line-notify@v1.1.0 if: failure() with: access_token: ${{ env.TOKEN_LINE }} message: | -Failure❌❌❌ Image: ${{env.IMAGE_NAME}} Version: ${{ github.event.inputs.IMAGE_VER }} By: ${{secrets.DOCKER_USER}} ``` 17. ทำการ login ไปที่ https://docker.frappet.com โดยใช้คำสั่งดังนี้ **หากไม่มีรหัส สามารถติดต่อหาพี่อุ้ม หรือพี่แจ๊ค เพื่อขอให้สร้าง username สำหรับใช้งาน Docker Registry** ```bash docker login docker.frappet.com ``` 18. การที่จะรัน Github Action ที่สร้างขึ้นมานั้นจะต้องใช้งาน act ซึ่งเป็น cli จะต้องทำการติดตั้งโปรแกรมนี้ก่อนใช้งาน ซึ่งสามารถทำได้หลายวิธี 1 ในวิธีนั้นคือติดตั้งผ่าน scoop ซึ่งการติดตั้งสามารถเข้าไปดูได้ที่ www.scoop.sh ซึ่งหลังจากติดตั้ง scoop แล้วสามารถติดตั้ง act ได้ผ่านคำสั่ง ```bash scoop install act ``` 19. หลังจากที่ติดตั้ง act แล้วจะทำการ run Github Action เพื่อทำการ Build และ Deploy ไปยัง Test Server โดยใช้คำสั่งนี้ ```bash act workflow_dispatch -W .github/workflows/{githib action file} --input IMAGE_VER={image version} -s DOCKER_USER={user name} -s DOCKER_PASS={password} -s SSH_PASSWORD={SSH Password} ``` 20. ซึ่งระบบจะทำการสร้าง Docker Image และ Push ขึ้นไปไว้ที่ Docker Registry และทำการ Deploy ที่ Test Server ให้โดยอัตโนมัติ ซึ่งหากทำการ Build and Deploy สำเร็จ จะแสดงข้อความดังนี้ ```bash | ======CMD====== | cd "/home/frappet/docker/bma-ehr-report-v2" | docker-compose pull | docker-compose up -d | echo "report-1.0.3"> success | | ======END====== Pulling bma-ehr-report-v2 ... done Recreating bma-ehr-report-v2_bma-ehr-report-v2_1 ... done | err: | ============================================== | ✅ Successfully executed commands to all host. | ============================================== [release-dev/release-dev] ✅ Success - Main Reload docker compose [release-dev/release-dev] ⭐ Run Main snow-actions/line-notify@v1.1.0 [release-dev/release-dev] 🐳 docker cp src=C:\Users\***\.cache\act/snow-actions-line-notify@v1.1.0/ dst=/var/run/act/actions/snow-actions-line-notify@v1.1.0/ [release-dev/release-dev] 🐳 docker exec cmd=[node /var/run/act/actions/snow-actions-line-notify@v1.1.0/index.js] user= workdir= | {"status":200,"message":"ok"} [release-dev/release-dev] ✅ Success - Main snow-actions/line-notify@v1.1.0 [release-dev/release-dev] ⭐ Run Post Build and load local docker image [release-dev/release-dev] 🐳 docker exec cmd=[node /var/run/act/actions/docker-build-push-action@v3/dist/index.js] user= workdir= [release-dev/release-dev] ❓ ::group::Removing temp folder /tmp/docker-build-push-3HKDLy [release-dev/release-dev] ❓ ::endgroup:: [release-dev/release-dev] ✅ Success - Post Build and load local docker image [release-dev/release-dev] ⭐ Run Post Login in to registry [release-dev/release-dev] 🐳 docker exec cmd=[node /var/run/act/actions/docker-login-action@v2/dist/index.js] user= workdir= [release-dev/release-dev] 💬 ::debug::Exec.getExecOutput: docker logout docker.frappet.com | [command]/usr/bin/docker logout docker.frappet.com | Removing login credentials for docker.frappet.com [release-dev/release-dev] ✅ Success - Post Login in to registry [release-dev/release-dev] ⭐ Run Post Set up Docker Buildx [release-dev/release-dev] 🐳 docker exec cmd=[node /var/run/act/actions/docker-setup-buildx-action@v2/dist/index.js] user= workdir= [release-dev/release-dev] ❓ ::group::Removing builder [release-dev/release-dev] 💬 ::debug::Buildx.isStandalone: false [release-dev/release-dev] 💬 ::debug::Exec.getExecOutput: docker buildx inspect builder-4a7bfe0e-828f-4d89-aa5a-7afc470cb2bf [release-dev/release-dev] 💬 ::debug::Builder.exists: true [release-dev/release-dev] 💬 ::debug::Buildx.isStandalone: false | [command]/usr/bin/docker buildx rm builder-4a7bfe0e-828f-4d89-aa5a-7afc470cb2bf | builder-4a7bfe0e-828f-4d89-aa5a-7afc470cb2bf removed [release-dev/release-dev] ❓ ::endgroup:: [release-dev/release-dev] ❓ ::group::Cleaning up certificates [release-dev/release-dev] ❓ ::endgroup:: [release-dev/release-dev] ✅ Success - Post Set up Docker Buildx [release-dev/release-dev] 🏁 Job succeeded ``` 21. หากเป็นการ Build เพื่อ Update Service เดิมสามารถเริ่มต้นได้ที่ ข้อ 19 ได้เลย ## Production Environment 1. Environment Diagram ![รูปภาพที่ 1 - 3 ](images/buildanddeploy/build1-3.png#center) 2. หลักการทำงานจะคล้ายๆกับ Test Environment เพียงแต่ว่าตัวฐานข้อมูล mySQL จะถูกสร้างขึ้นเป็น container ของตัว Production โดยเฉพาะ 3. เนื่องจากเราได้ทำขั้นตอนของการ Build Docker Image ไปในระหว่างการทดสอบระบบแล้ว เราจึงไม่ต้องทำขั้นตอนการ Build Image ซ้ำอีกรอบ เนื่องจาก Image ทั้งหมดจะถูก push ขึ้นไปที่ [https://docker.frappet.com](https://docker.frappet.com) แล้วนั่นเอง 4. ให้ทำการเพิ่ม Service ที่เราต้องการเพิ่มเติมไปที่ docker-compose File โดยอ้างอิงจาก docker-compose file ของ Service ตัวทดสอบ โดยแก้ไข URL, PathPrefix และ Traefik RuleName ให้ไม่ซ้ำกัน โดยดูจากตัวอย่าง File ด้านล่าง ```yaml version: "3.4" services: bma-mysql-test1: image: mysql:8.0.17 command: ["--max_connections=5000"] restart: unless-stopped ports: - "4061:3306" volumes: - ./mysql-data:/var/lib/mysql - ./init_mysql:/docker-entrypoint-initdb.d/:ro environment: TZ: Asia/Bangkok MYSQL_ROOT_PASSWORD: adminVM123 MYSQL_DATABASE: bma_ehr MYSQL_USER: frappet MYSQL_PASSWORD: P@ssw0rd networks: - bma-ehr bma-mongodb-test1: image: mongo:4.2.0 command: [--auth] restart: unless-stopped ports: - "4062:27017" volumes: - ./mongo-data:/data/db environment: TZ: Asia/Bangkok MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: adminVM123 networks: - bma-ehr bma-ehr-test1: image: docker.frappet.com/ehr/bma-ehr-app:latest restart: unless-stopped labels: - traefik.enable=true - traefik.http.routers.bma-ehr-test1.rule=Host(`bma-ehr.frappet.com`) - "traefik.http.routers.bma-ehr-test1.entrypoints=unsecure" environment: TZ: Asia/Bangkok VITE_COMPETITIVE_EXAM_PANEL: "https://bma-dashboard.frappet.synology.me/goto/D222MQQVk?orgId=1" VITE_QUALIFY_DISABLE_EMAM_PANEL: "https://bma-dashboard.frappet.synology.me/goto/i0RoGQw4k?orgId=1" VITE_QUALIFY_EXAM_PANEL: "https://bma-dashboard.frappet.synology.me/goto/RQXtGQQ4z?orgId=1" VITE_S3CLUSTER_PUBLIC_URL: "https://s3cluster.frappet.com/bma-ehr-fpt/organization/strueture/" networks: - bma-ehr bma-ehr-metadata-test1: image: docker.frappet.com/ehr/bma-ehr-metadata-service:latest restart: unless-stopped # ports: # - "4065:80" volumes: - ./appsettings-metadata.json:/app/appsettings.json - ./appsettings-metadata.json:/app/appsettings.Development.json labels: - "traefik.enable=true" - "traefik.http.routers.bma-ehr-metadata-test1.rule=Host(`bma-ehr.frappet.com`) && PathPrefix(`/api/v1`)" - "traefik.http.routers.bma-ehr-metadata-test1.entrypoints=unsecure" environment: TZ: Asia/Bangkok # ASPNETCORE_ENVIRONMENT: Development networks: - bma-ehr bma-ehr-profile-test1: image: docker.frappet.com/ehr/bma-ehr-profile-service:latest restart: always # ports: # - "4066:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-profile.json:/app/appsettings.json - ./appsettings-profile.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok # ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-profile-test1.rule=Host(`bma-ehr.frappet.com`) && PathPrefix(`/api/v1/profile`)" networks: - bma-ehr bma-ehr-organization-test1: image: docker.frappet.com/ehr/bma-ehr-organization-service:latest restart: unless-stopped # ports: # - "4067:80" volumes: - ./appsettings-organization.json:/app/appsettings.json - ./appsettings-organization.json:/app/appsettings.Development.json labels: - "traefik.enable=true" - "traefik.http.routers.bma-ehr-organization-test1.rule=Host(`bma-ehr.frappet.com`) && (PathPrefix(`/api/v1/Organization`)||PathPrefix(`/api/v1/PositionMaster`)||PathPrefix(`/api/v1/report2`))" - "traefik.http.routers.bma-ehr-organization-test1.entrypoints=unsecure" environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development networks: - bma-ehr bma-ehr-recruit-test1: image: docker.frappet.com/ehr/bma-ehr-recruit-service:latest restart: unless-stopped # ports: # - "4068:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-recruit.json:/app/appsettings.json - ./appsettings-recruit.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-api-recruit-test1.rule=Host(`bma-ehr.frappet.com`) && PathPrefix(`/api/v1/recruit`)" networks: - bma-ehr bma-ehr-report-test1: image: docker.frappet.com/ehr/bma-ehr-report-service:latest restart: unless-stopped # ports: # - "5026:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-report.json:/app/appsettings.json - ./appsettings-report.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok # ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-api-report-test1.rule=Host(`bma-ehr.frappet.com`) && PathPrefix(`/api/v1/report`)" networks: - bma-ehr # เว็บไซต์สำหรับรับสมัครสอบคัดเลือก : bma-apply.frappet.com bma-ehr-candidate-register-test1: image: docker.frappet.com/ehr/bma-ehr-recruit-exam:latest restart: unless-stopped environment: TZ: Asia/Bangkok VITE_API_URI_CONFIG: "https://bma-ehr.frappet.com/api/v1" labels: - traefik.enable=true - traefik.http.routers.bma-ehr-candidate-register-test1.rule=Host(`bma-apply.frappet.com`) networks: - bma-ehr bma-ehr-recruit-exam-test1: image: docker.frappet.com/ehr/bma-ehr-recruit-exam-service:latest restart: unless-stopped ports: - "4069:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-recruit-exam.json:/app/appsettings.json - ./appsettings-recruit-exam.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-candidate-exam-test1.rule=Host(`bma-ehr.frappet.com`) && ( PathPrefix(`/api/v1/cms`) || PathPrefix(`/api/v1/candidate`) )" networks: - bma-ehr # เว็บไซต์ศูนย์ข้อมูลการสรรหาบุคคลของกรุงเทพมหานคร(CMS): bma-recruit.frappet.com bma-ehr-qualifying-exam-cms-test1: image: docker.frappet.com/demo/qualifying-exam-cms:latest restart: unless-stopped # ports: # - "4028:80" environment: TZ: Asia/Bangkok API_CMS_URL: "https://bma-ehr.frappet.com/api/v1/cms" API_QUALIFYING_URL: "https://bma-ehr.frappet.com/api/v1/cms" API_COMPETITIVE_URL: "https://bma-ehr.frappet.com/api/v1/recruit" PUBLIC_URL_REGISTER_QUALIFY_EXAM: "https://bma-apply.frappet.com" labels: - traefik.enable=true - traefik.http.routers.bma-ehr-qualifying-exam-cms-test1.rule=Host(`bma-recruit.frappet.com`) networks: - bma-ehr bma-ehr-insignia-test1: image: docker.frappet.com/ehr/bma-ehr-insignia-service:latest restart: unless-stopped # ports: # - "4031:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-insignia.json:/app/appsettings.json - ./appsettings-insignia.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-insignia-test1.rule=Host(`bma-ehr.frappet.com`) && (PathPrefix(`/api/v1/insignia`))" networks: - bma-ehr bma-ehr-org-employee-test1: image: docker.frappet.com/ehr/bma-ehr-org-employee-service:latest restart: unless-stopped # ports: # - "4026:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-org-employee.json:/app/appsettings.json - ./appsettings-org-employee.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-org-employee-test1.rule=Host(`bma-ehr.frappet.com`) && (PathPrefix(`/api/v1/organization-employee`))" networks: - bma-ehr bma-ehr-placement-test1: image: docker.frappet.com/ehr/bma-ehr-placement-service:latest restart: unless-stopped # ports: # - "4032:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-placement.json:/app/appsettings.json - ./appsettings-placement.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-placement-test1.rule=Host(`bma-ehr.frappet.com`) && (PathPrefix(`/api/v1/placement`))" networks: - bma-ehr bma-ehr-retirement-test1: image: docker.frappet.com/ehr/bma-ehr-retirement-service:latest restart: unless-stopped # ports: # - "4030:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-retirement.json:/app/appsettings.json - ./appsettings-retirement.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-retirement-test1.rule=Host(`bma-ehr.frappet.com`) && (PathPrefix(`/api/v1/retirement`))" networks: - bma-ehr bma-ehr-report-v2-test1: image: docker.frappet.com/ehr/bma-ehr-report-v2-service:latest # image: docker.frappet.com/ehr/bma-ehr-report:test-v2 restart: unless-stopped # ports: # - "6029:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-report-v2.json:/app/appsettings.json - ./appsettings-report-v2.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-api-report-v2-test1.rule=Host(`bma-ehr.frappet.com`) && PathPrefix(`/api/v2/report`)" networks: - bma-ehr bma-ehr-probation-test1: image: docker.frappet.com/ehr/bma-ehr-node-service:version-1.0.1 restart: unless-stopped # ports: # - "4033:8080" # volumes: # - ./wwwroot:/app/wwwroot # - ./appsettings.json:/app/appsettings.json # - ./appsettings.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development HOST: "0.0.0.0" PORT: "8080" DB_HOST: "bma-mysql-test1" DB_PORT: "3306" DB_USER: "root" DB_NAME: "bma_ehr" DB_PASSWORD: "adminVM123" API_URL: "https://bma-ehr.frappet.com/api/v1" KEYCLOAK_URL: "https://id.frappet.synology.me/realms/bma-ehr" KEYCLOAK_KEY: "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI" KEYCLOAK_REALM: "bma-ehr" labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-probation-test1.rule=Host(`bma-ehr.frappet.com`) && (PathPrefix(`/api/v1/probation`))" networks: - bma-ehr bma-ehr-command-test1: image: docker.frappet.com/ehr/bma-ehr-command-service:latest restart: unless-stopped # ports: # - "6026:80" volumes: - ./wwwroot:/app/wwwroot - ./appsettings-command.json:/app/appsettings.json - ./appsettings-command.json:/app/appsettings.Development.json environment: TZ: Asia/Bangkok ASPNETCORE_ENVIRONMENT: Development labels: - traefik.enable=true - "traefik.http.routers.bma-ehr-command-test1.rule=Host(`bma-ehr.frappet.com`) && (PathPrefix(`/api/v1/order`) || PathPrefix(`/api/v1/message`))" networks: - bma-ehr bma-ehr-manual-test1: image: docker.frappet.com/ehr/bma-ehr-manual:latest restart: always # ports: # - "6023:80" environment: TZ: Asia/Bangkok labels: - traefik.enable=true - traefik.http.routers.bma-ehr-manual-test1.rule=Host(`bma-ehr-manual.frappet.com`) networks: - bma-ehr bma-ehr-user-test1: image: docker.frappet.com/ehr/bma-ehr-user:latest restart: unless-stopped # ports: # - "6022:80" environment: TZ: Asia/Bangkok VITE_API_URI_CONFIG: "https://bma-ehr.frappet.com/api/v1" labels: - traefik.enable=true - traefik.http.routers.bma-ehr-user-test1.rule=Host(`bma-ehr-user.frappet.com`) - "traefik.http.routers.bma-ehr-user-test1.entrypoints=unsecure" networks: - bma-ehr networks: bma-ehr: external: true ``` 5. หลังจากนั้นให้เข้าไปที่ folder ของตัวระบบ Production แล้วรันคำสั่ง ```bash docker compose pull ``` 6. ระบบจะ pull Docker Image ทั้งหมดตามที่เราประกาศไว้ใน File Docker Compose 7. หลังจากนั้นรันคำสั่งนี้ เพื่อให้ทำการ Reload Docker Container เพื่อให้ระบบทำการ Update มาใช้ Image Version ล่าสุด ```bash docker compose up -d ``` 8. หากต้องการดู log แต่ละ service ให้ใช้คำสั่ง ```bash docker compose logs -f {service name} ``` 9. โดยการดู service name สามารถใช้คำสั่งนี้เพื่อทำการ List Container ขึ้นมา ```bash docker compose ps ``` 10. ซึ่งระบบจะแสดง Container ทั้งหมดของ docker compose file นี้ขึ้นมาให้เราสามารถดูได้ ```bash NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS bma-ehr-test1-bma-ehr-candidate-register-test1-1 docker.frappet.com/ehr/bma-ehr-recruit-exam:latest "/usr/local/bin/entr…" bma-ehr-candidate-register-test1 3 days ago Up 23 hours 80/tcp bma-ehr-test1-bma-ehr-command-test1-1 docker.frappet.com/ehr/bma-ehr-command-service:latest "dotnet BMA.EHR.Comm…" bma-ehr-command-test1 12 hours ago Up 12 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-insignia-test1-1 docker.frappet.com/ehr/bma-ehr-insignia-service:latest "dotnet BMA.EHR.Insi…" bma-ehr-insignia-test1 12 hours ago Up 12 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-manual-test1-1 docker.frappet.com/ehr/bma-ehr-manual:latest "/docker-entrypoint.…" bma-ehr-manual-test1 3 days ago Up 23 hours 80/tcp bma-ehr-test1-bma-ehr-metadata-test1-1 docker.frappet.com/ehr/bma-ehr-metadata-service:latest "dotnet BMA.EHR.Meta…" bma-ehr-metadata-test1 3 days ago Up 23 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-org-employee-test1-1 docker.frappet.com/ehr/bma-ehr-org-employee-service:latest "dotnet BMA.EHR.Orga…" bma-ehr-org-employee-test1 3 days ago Up 23 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-organization-test1-1 docker.frappet.com/ehr/bma-ehr-organization-service:latest "dotnet BMA.EHR.Orga…" bma-ehr-organization-test1 3 days ago Up 23 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-placement-test1-1 docker.frappet.com/ehr/bma-ehr-placement-service:latest "dotnet BMA.EHR.Plac…" bma-ehr-placement-test1 12 hours ago Up 12 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-probation-test1-1 docker.frappet.com/ehr/bma-ehr-node-service:version-1.0.1 "docker-entrypoint.s…" bma-ehr-probation-test1 About an hour ago Up About an hour 8080/tcp bma-ehr-test1-bma-ehr-profile-test1-1 docker.frappet.com/ehr/bma-ehr-profile-service:latest "dotnet BMA-EHR-Prof…" bma-ehr-profile-test1 12 hours ago Up 12 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-qualifying-exam-cms-test1-1 docker.frappet.com/demo/qualifying-exam-cms:latest "docker-entrypoint.s…" bma-ehr-qualifying-exam-cms-test1 3 days ago Up 23 hours 80/tcp bma-ehr-test1-bma-ehr-recruit-exam-test1-1 docker.frappet.com/ehr/bma-ehr-recruit-exam-service:latest "dotnet BMA.EHR.Recu…" bma-ehr-recruit-exam-test1 27 hours ago Up 23 hours 443/tcp, 0.0.0.0:4069->80/tcp, :::4069->80/tcp bma-ehr-test1-bma-ehr-recruit-test1-1 docker.frappet.com/ehr/bma-ehr-recruit-service:latest "dotnet BMA.EHR.Recr…" bma-ehr-recruit-test1 27 hours ago Up 23 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-report-test1-1 docker.frappet.com/ehr/bma-ehr-report-service:latest "dotnet BMA.EHR.Repo…" bma-ehr-report-test1 3 days ago Up 23 hours 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-report-v2-test1-1 sha256:bad691df0d3914a2a50fc8c001d55c4ee8e59cd298537cc878a77bc7565c8993 "dotnet BMA.EHR.Repo…" bma-ehr-report-v2-test1 About an hour ago Up About an hour 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-retirement-test1-1 docker.frappet.com/ehr/bma-ehr-retirement-service:latest "dotnet BMA.EHR.Reti…" bma-ehr-retirement-test1 About an hour ago Up About an hour 80/tcp, 443/tcp bma-ehr-test1-bma-ehr-test1-1 docker.frappet.com/ehr/bma-ehr-app:latest "/usr/local/bin/entr…" bma-ehr-test1 About an hour ago Up About an hour 80/tcp bma-ehr-test1-bma-ehr-user-test1-1 docker.frappet.com/ehr/bma-ehr-user:latest "/usr/local/bin/entr…" bma-ehr-user-test1 27 hours ago Up 23 hours 80/tcp bma-ehr-test1-bma-mongodb-test1-1 mongo:4.2.0 "docker-entrypoint.s…" bma-mongodb-test1 3 days ago Up 23 hours 0.0.0.0:4062->27017/tcp, :::4062->27017/tcp bma-ehr-test1-bma-mysql-test1-1 mysql:8.0.17 "docker-entrypoint.s…" bma-mysql-test1 3 days ago Up 23 hours 33060/tcp, 0.0.0.0:4061->3306/tcp, :::4061->3306/tcp ``` 11. หากเราต้องการ shell เข้าไปที่ตัว container สามารถใช้คำสั่งนี้ ```bash docker compose exec -it {service name} bash ``` ## Production Environment (BMA Data Center) 1. ใน DC จะเปลี่ยนมาใช้ฐานข้อมูล Oracle ซึ่งระบบได้มีการ build docker image ที่เป็น version สำหรับติดต่อฐานข้อมูล Oracle ไว้แล้ว 2. การติดตั้งระบบให้ทำการต่อ VPN เข้าไปที่ Network ของทางกทม.ก่อน 3. ทำการ ssh ไปที่ Application Server ```bash ssh psbehrapp01 ``` 4. เมื่อ ssh เข้ามาแล้วจะพอหน้าจอแบบนี้ ```bash Linux vm-BMA04-00022 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue Jun 4 09:25:07 2024 from 172.31.68.238 administrator@vm-BMA04-00022:~$ ``` 5. เข้าไปที่ folder docker/bma-ehr จะพบกับไฟล์ setup และ docker compose ที่ใช้สำหรับติดตั้งระบบ ```bash administrator@vm-BMA04-00022:~/docker/bma-ehr$ ls -la total 96 drwxr-xr-x 3 administrator administrator 4096 May 17 09:42 . drwxr-xr-x 5 administrator administrator 4096 May 17 09:39 .. -rw-r--r-- 1 administrator administrator 1647 May 17 11:38 appsettings-command.json -rw-r--r-- 1 administrator administrator 2664 May 17 11:38 appsettings-discipline.json -rw-r--r-- 1 administrator administrator 1946 May 17 11:39 appsettings-insignia.json -rw-r--r-- 1 administrator administrator 2302 May 17 11:39 appsettings-leave.json -rw-r--r-- 1 administrator administrator 1683 May 17 10:20 appsettings-metadata.json -rw-r--r-- 1 administrator administrator 1763 May 17 10:28 appsettings-organization.json -rw-r--r-- 1 administrator administrator 1511 May 17 11:47 appsettings-org-employee.json -rw-r--r-- 1 administrator administrator 1946 May 17 11:47 appsettings-placement.json -rw-r--r-- 1 administrator administrator 1511 May 17 11:12 appsettings-profile.json -rw-r--r-- 1 administrator administrator 1919 May 17 11:47 appsettings-recruit-exam.json -rw-r--r-- 1 administrator administrator 1871 May 17 11:49 appsettings-recruit.json -rw-r--r-- 1 administrator administrator 2222 May 17 11:49 appsettings-report.json -rw-r--r-- 1 administrator administrator 2296 May 17 11:49 appsettings-report-v2.json -rw-r--r-- 1 administrator administrator 2048 May 17 11:49 appsettings-retirement.json -rw-r--r-- 1 administrator administrator 28113 May 21 12:39 docker-compose.yml drwxr-xr-x 3 administrator administrator 4096 May 17 09:42 wwwroot administrator@vm-BMA04-00022:~/docker/bma-ehr$ ``` 6. รายละเอียดใน docker-compose.yml มีดังนี้ ```yaml administrator@vm-BMA04-00022:~/docker/bma-ehr$ ls -la total 96 drwxr-xr-x 3 administrator administrator 4096 May 17 09:42 . drwxr-xr-x 5 administrator administrator 4096 May 17 09:39 .. -rw-r--r-- 1 administrator administrator 1647 May 17 11:38 appsettings-command.json -rw-r--r-- 1 administrator administrator 2664 May 17 11:38 appsettings-discipline.json -rw-r--r-- 1 administrator administrator 1946 May 17 11:39 appsettings-insignia.json -rw-r--r-- 1 administrator administrator 2302 May 17 11:39 appsettings-leave.json -rw-r--r-- 1 administrator administrator 1683 May 17 10:20 appsettings-metadata.json -rw-r--r-- 1 administrator administrator 1763 May 17 10:28 appsettings-organization.json -rw-r--r-- 1 administrator administrator 1511 May 17 11:47 appsettings-org-employee.json -rw-r--r-- 1 administrator administrator 1946 May 17 11:47 appsettings-placement.json -rw-r--r-- 1 administrator administrator 1511 May 17 11:12 appsettings-profile.json -rw-r--r-- 1 administrator administrator 1919 May 17 11:47 appsettings-recruit-exam.json -rw-r--r-- 1 administrator administrator 1871 May 17 11:49 appsettings-recruit.json -rw-r--r-- 1 administrator administrator 2222 May 17 11:49 appsettings-report.json -rw-r--r-- 1 administrator administrator 2296 May 17 11:49 appsettings-report-v2.json -rw-r--r-- 1 administrator administrator 2048 May 17 11:49 appsettings-retirement.json -rw-r--r-- 1 administrator administrator 28113 May 21 12:39 docker-compose.yml drwxr-xr-x 3 administrator administrator 4096 May 17 09:42 wwwroot administrator@vm-BMA04-00022:~/docker/bma-ehr$ ``` 7. หลังจากนั้นให้เข้าไปที่ folder ของตัวระบบ Production แล้วรันคำสั่ง ```bash docker compose pull ``` 8. ระบบจะ pull Docker Image ทั้งหมดตามที่เราประกาศไว้ใน File Docker Compose 9. หลังจากนั้นรันคำสั่งนี้ เพื่อให้ทำการ Reload Docker Container เพื่อให้ระบบทำการ Update มาใช้ Image Version ล่าสุด ```bash docker compose up -d ``` 10. หากต้องการดู log แต่ละ service ให้ใช้คำสั่ง ```bash docker compose logs -f {service name} ``` 11. โดยการดู service name สามารถใช้คำสั่งนี้เพื่อทำการ List Container ขึ้นมา ```bash docker compose ps ``` 12. ซึ่งระบบจะแสดง Container ทั้งหมดของ docker compose file นี้ขึ้นมาให้เราสามารถดูได้ ```bash administrator@vm-BMA04-00022:~/docker/bma-ehr$ docker compose ps WARN[0000] /home/administrator/docker/bma-ehr/docker-compose.yml: `version` is obsolete NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS bma-ehr-checkin-oracle docker.frappet.com/ehr/bma-ehr-checkin:latest "/usr/local/bin/entr…" bma-ehr-checkin-oracle 2 weeks ago Up 2 weeks 80/tcp bma-ehr-command-oracle docker.frappet.com/ehr/oracle/bma-ehr-command-service:latest "dotnet BMA.EHR.Comm…" bma-ehr-command-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-discipline-oracle docker.frappet.com/ehr/oracle/bma-ehr-discipline-service:latest "dotnet BMA.EHR.Disc…" bma-ehr-discipline-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-evaluation-oracle docker.frappet.com/ehr/oracle/bma-ehr-evaluation-service:latest "docker-entrypoint.s…" bma-ehr-evaluation-oracle 2 weeks ago Up 2 weeks 0.0.0.0:14039->8082/tcp, :::14039->8082/tcp bma-ehr-insignia-oracle docker.frappet.com/ehr/oracle/bma-ehr-insignia-service:latest "dotnet BMA.EHR.Insi…" bma-ehr-insignia-oracle 2 weeks ago Up 2 weeks 443/tcp, 0.0.0.0:15031->80/tcp, :::15031->80/tcp bma-ehr-kpi-oracle docker.frappet.com/ehr/oracle/bma-ehr-kpi-service:latest "docker-entrypoint.s…" bma-ehr-kpi-oracle 2 weeks ago Restarting (1) 59 seconds ago bma-ehr-leave-oracle docker.frappet.com/ehr/oracle/bma-ehr-leave-service:latest "dotnet BMA.EHR.Leav…" bma-ehr-leave-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-metadata-oracle docker.frappet.com/ehr/oracle/bma-ehr-metadata-service:latest "dotnet BMA.EHR.Meta…" bma-ehr-metadata-oracle 2 weeks ago Up 2 weeks 443/tcp, 0.0.0.0:14065->80/tcp, :::14065->80/tcp bma-ehr-oracle docker.frappet.com/ehr/bma-ehr-app:latest "/usr/local/bin/entr…" bma-ehr-oracle 2 weeks ago Up 2 weeks 80/tcp bma-ehr-org-employee-oracle docker.frappet.com/ehr/oracle/bma-ehr-org-employee-service:latest "dotnet BMA.EHR.Orga…" bma-ehr-org-employee-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-org-oracle docker.frappet.com/ehr/oracle/bma-ehr-org-service:latest "docker-entrypoint.s…" bma-ehr-org-oracle 2 weeks ago Up 2 weeks 0.0.0.0:4038->8081/tcp, :::4038->8081/tcp bma-ehr-placement-oracle docker.frappet.com/ehr/oracle/bma-ehr-placement-service:latest "dotnet BMA.EHR.Plac…" bma-ehr-placement-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-probation-oracle docker.frappet.com/ehr/oracle/bma-ehr-node-service:latest "docker-entrypoint.s…" bma-ehr-probation-oracle 13 days ago Up 13 days 8080/tcp bma-ehr-profile-oracle docker.frappet.com/ehr/oracle/bma-ehr-profile-service:latest "dotnet BMA-EHR-Prof…" bma-ehr-profile-oracle 2 weeks ago Up 2 weeks 443/tcp, 0.0.0.0:14066->80/tcp, :::14066->80/tcp bma-ehr-publish-oracle docker.frappet.com/ehr/bma-ehr-publish:latest "/usr/local/bin/entr…" bma-ehr-publish-oracle 2 weeks ago Up 2 weeks 80/tcp bma-ehr-report-oracle docker.frappet.com/ehr/oracle/bma-ehr-report-service:latest "dotnet BMA.EHR.Repo…" bma-ehr-report-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-report-v2-oracle docker.frappet.com/ehr/oracle/bma-ehr-report-v2-service:latest "dotnet BMA.EHR.Repo…" bma-ehr-report-v2-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-retirement-oracle docker.frappet.com/ehr/oracle/bma-ehr-retirement-service:latest "dotnet BMA.EHR.Reti…" bma-ehr-retirement-oracle 2 weeks ago Up 2 weeks 80/tcp, 443/tcp bma-ehr-salary-oracle docker.frappet.com/ehr/oracle/bma-ehr-salary-service:latest "docker-entrypoint.s…" bma-ehr-salary-oracle 2 weeks ago Up 2 weeks 0.0.0.0:14040->8081/tcp, :::14040->8081/tcp bma-ehr-user-oracle docker.frappet.com/ehr/bma-ehr-user:latest "/usr/local/bin/entr…" bma-ehr-user-oracle 2 weeks ago Up 2 weeks 80/tcp bma-mongodb-oracle mongo:4.2.0 "docker-entrypoint.s…" bma-mongodb-oracle 2 weeks ago Up 2 weeks 0.0.0.0:14062->27017/tcp, :::14062->27017/tcp administrator@vm-BMA04-00022:~/docker/bma-ehr$ ```