แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แžขแžแŸ’แžแž”แž‘แž“แŸแŸ‡แž“แžนแž„แž˜แžถแž“แž€แžถแžšแž…แžถแž”แŸ‹แžขแžถแžšแž˜แŸ’แž˜แžŽแŸแž…แŸ†แž–แŸ„แŸ‡แž‘แžถแŸ†แž„แžขแŸ’แž“แž€แžŸแžถแž€แž›แŸ’แž”แž„ แž“แžทแž„แžขแŸ’แž“แž€แžขแž—แžทแžœแžŒแŸ’แžแž“แŸ แž”แŸ‰แžปแž“แŸ’แžแŸ‚แžแŸ’แžšแžผแžœแž”แžถแž“แž”แž˜แŸ’แžšแžปแž„แž‘แžปแž€แž‡แžถแž…แž˜แŸ’แž”แž„แžŸแž˜แŸ’แžšแžถแž”แŸ‹แžขแŸ’แž“แž€แž‡แŸ†แž“แžถแž‰แž•แŸ’แž“แŸ‚แž€แžŸแŸ’แžœแŸแž™แž”แŸ’แžšแžœแžแŸ’แžแžทแž€แž˜แŸ’แž˜แžŠแŸ‚แž›แž”แŸ’แžšแžˆแž˜แž“แžนแž„แž”แž‰แŸ’แž แžถแž“แŸƒแž€แžถแžšแžŠแŸ†แžกแžพแž„ GitLab CI/CD แžŸแž˜แŸ’แžšแžถแž”แŸ‹แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž›แž“แŸ…แž€แŸ’แž“แžปแž„แž›แž€แŸ’แžแžแžŽแŸ’แžŒแž“แŸƒแž’แž“แž’แžถแž“แž แŸแžŠแŸ’แž‹แžถแžšแž…แž“แžถแžŸแž˜แŸ’แž–แŸแž“แŸ’แž’แž˜แžทแž“แž‚แŸ’แžšแž”แŸ‹แž‚แŸ’แžšแžถแž“แŸ‹ แž“แžทแž„/แžฌแžขแžœแžแŸ’แžแž˜แžถแž“แž“แŸƒแž€แžปแž„แžแžบแž“แŸแžšแŸ” แžœแŸแž‘แžทแž€แžถ orchestration แŸ” แžแŸ’แž‰แžปแŸ†แž“แžนแž„แž”แŸ’แžšแžถแž”แŸ‹แžขแŸ’แž“แž€แž–แžธแžšแž”แŸ€แž”แžšแŸ€แž”แž…แŸ†แž€แžถแžšแžŠแžถแž€แŸ‹แž–แž„แŸ’แžšแžถแž™แž”แžšแžทแžŸแŸ’แžแžถแž“แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ docker compose แž“แŸ…แž›แžพแž€แž˜แŸ’แž˜แžœแžทแž’แžธแžšแžแŸ‹แžŸแŸ‚แž› GitLab แžแŸ‚แž˜แžฝแž™ แž แžพแž™แžŠแžผแž…แŸ’แž“แŸแŸ‡แž“แŸ…แž–แŸแž›แžŠแžถแž€แŸ‹แž–แž„แŸ’แžšแžถแž™แž”แžšแžทแžŸแŸ’แžแžถแž“แž‡แžถแž…แŸ’แžšแžพแž“ แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŠแŸ‚แž›แž”แžถแž“แž”แžพแž€แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž˜แžทแž“แžšแŸ†แžแžถแž“แžŠแž›แŸ‹แž‚แŸ’แž“แžถแž‘แŸ…แžœแžทแž‰แž‘แŸ…แž˜แž€แŸ”


แž˜แžถแžแžทแž€แžถ

แžแž˜แŸ’แžšแžผแžœแž€แžถแžšแž‡แžถแž˜แžปแž“แŸ”

  1. แž“แŸ…แž€แŸ’แž“แžปแž„แž€แžถแžšแžขแž“แžปแžœแžแŸ’แžแžšแž”แžŸแŸ‹แžแŸ’แž‰แžปแŸ† แžœแžถแž‡แžถแžšแžฟแž™แŸ—แž”แžถแž“แž€แžพแžแžกแžพแž„แžŠแŸ‚แž›แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžŸแž˜แžถแž แžšแžŽแž€แž˜แŸ’แž˜แžแŸ’แžšแžผแžœแž”แžถแž“ "แž–แŸ’แž™แžถแž”แžถแž›" แž›แžพแž‚แž˜แŸ’แžšแŸ„แž„แŸ” แž แžพแž™แž‡แžถแžšแžฟแž™แŸ—แž”แž‰แŸ’แž แžถแžŠแŸ†แž”แžผแž„ แž“แžทแž„แžŸแŸ†แžแžถแž“แŸ‹แž”แŸ†แž•แžปแžแž‚แžบแž”แŸ†แž–แž„แŸ‹ CI แžŠแŸ‚แž›แž€แŸ’แž“แžปแž„แž“แŸ„แŸ‡ แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž› แž€แŸ†แž–แžปแž„แžแŸ’แžšแžผแžœแž”แžถแž“แžขแž—แžทแžœแžŒแŸ’แž แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžแŸ’แžšแžผแžœแž”แžถแž“แžขแž“แžปแžœแžแŸ’แžแž“แŸ…แž€แŸ’แž“แžปแž„แž”แžšแžทแž™แžถแž€แžถแžŸแžขแž—แžทแžœแžŒแŸ’แžแž“แŸ/แžŠแŸ†แžŽแžถแž€แŸ‹แž€แžถแž›แŸ” แž“แŸแŸ‡แž”แžŽแŸ’แžแžถแž›แžฑแŸ’แž™แž˜แžถแž“แž”แž‰แŸ’แž แžถแž˜แžฝแž™แž…แŸ†แž“แžฝแž“:

    • แžŠแŸ„แž™แžŸแžถแžšแžแŸ‚แž˜แžถแž“แž–แžทแž€แžถแžšแž—แžถแž–แž“แŸ…แž€แŸ’แž“แžปแž„แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แž‡แžถแž€แŸ‹แž›แžถแž€แŸ‹แž˜แžฝแž™แž€แŸ†แžกแžปแž„แž–แŸแž›แž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž› แžŸแŸ€แž‚แŸ’แžœแžธแžŸแžถแž€แž›แŸ’แž”แž„แžขแžถแž…แž“แžนแž„แžแŸ’แžšแžผแžœแžแžผแž…แžแžถแžแžŠแŸ„แž™แžŸแžถแžšแž‘แžทแž“แŸ’แž“แž“แŸแž™แžŠแŸ‚แž›แžแžผแž…แŸ” แž˜แžถแž“แž€แžšแžŽแžธแž‡แžถแž…แŸ’แžšแžพแž“แž“แŸ…แž–แŸแž›แžŠแŸ‚แž›แž€แžถแžšแž•แŸ’แž‰แžพแžŸแŸ†แžŽแžพแž‡แžถแž˜แžฝแž™แž“แžนแž„แž‘แž˜แŸ’แžšแž„แŸ‹ JSON แžŠแŸ‚แž›แžแžผแž…แž”แžถแž“แž’แŸ’แžœแžพแžฑแŸ’แž™แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แž‚แžถแŸ†แž„ แžŠแŸ‚แž›แž’แŸ’แžœแžพแžฑแŸ’แž™แž€แžถแžšแžˆแžšแž˜แžทแž“แžขแžถแž…แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž”แžถแž“แž‘แžถแŸ†แž„แžŸแŸ’แžšแžปแž„แŸ”
    • แž€แžถแžšแžแž™แž…แžปแŸ‡แž“แŸƒแžŸแŸ€แž‚แŸ’แžœแžธแžŸแžถแž€แž›แŸ’แž”แž„แž“แŸ…แž–แŸแž›แžŠแŸ‚แž›แž‘แžทแž“แŸ’แž“แž“แŸแž™แžแŸแžŸแŸ’แžแž€แžพแž“แžกแžพแž„แŸ” แžแŸ’แž‰แžปแŸ†โ€‹แž‚แžทแžโ€‹แžแžถโ€‹แžœแžถโ€‹แž‚แŸ’แž˜แžถแž“โ€‹แž“แŸแž™โ€‹แž‘แŸโ€‹แž€แŸ’แž“แžปแž„โ€‹แž€แžถแžšโ€‹แž–แžทแž–แžŽแŸŒแž“แžถโ€‹แžขแŸ†แž–แžธโ€‹แžงแž‘แžถแž แžšแžŽแŸโ€‹แž˜แžฝแž™โ€‹แž‡แžถแž˜แžฝแž™โ€‹แž“แžนแž„โ€‹แž€แžถแžšโ€‹แžŸแž˜แŸ’แžขแžถแž / แžšแž˜แŸ€แž›โ€‹แžแŸ’แžšแžกแž”แŸ‹โ€‹แž˜แž€โ€‹แžœแžทแž‰โ€‹แž˜แžผแž›แžŠแŸ’แž‹แžถแž“โ€‹แž‘แžทแž“แŸ’แž“แž“แŸแž™แŸ” แž“แŸ…แž€แŸ’แž“แžปแž„แž€แžถแžšแžขแž“แžปแžœแžแŸ’แžแžšแž”แžŸแŸ‹แžแŸ’แž‰แžปแŸ† แžแŸ’แž‰แžปแŸ†แž˜แžทแž“แž‡แžฝแž”แž‚แž˜แŸ’แžšแŸ„แž„แžŠแŸ‚แž›แž“แžธแžแžทแžœแžทแž’แžธแž“แŸแŸ‡แžŠแŸ†แžŽแžพแžšแž€แžถแžšแžŠแŸ„แž™แžšแž›แžผแž“แž“แŸ„แŸ‡แž‘แŸแŸ”
    • แž แžถแž“แžทแž—แŸแž™แž“แŸƒแž€แžถแžšแžšแŸ†แžแžถแž“แžŠแž›แŸ‹แž˜แžปแžแž„แžถแžšแž“แŸƒแžŸแŸ€แž‚แŸ’แžœแžธแžŸแžถแž€แž›แŸ’แž”แž„แž“แŸ…แž–แŸแž›แžŸแžถแž€แž›แŸ’แž”แž„แž€แžถแžšแž€แŸ†แžŽแžแŸ‹แž”แŸ’แžšแž–แŸแž“แŸ’แž’แž‘แžผแž‘แŸ…แŸ” แžงแž‘แžถแž แžšแžŽแŸ แž‚แŸ„แž›แž€แžถแžšแžŽแŸแžขแŸ’แž“แž€แž”แŸ’แžšแžพแž”แŸ’แžšแžถแžŸแŸ‹/แž€แŸ’แžšแžปแž˜/แž–แžถแž€แŸ’แž™แžŸแž˜แŸ’แž„แžถแžแŸ‹/แž€แž˜แŸ’แž˜แžœแžทแž’แžธแŸ”
    • แž‘แžทแž“แŸ’แž“แž“แŸแž™แžŸแžถแž€แž›แŸ’แž”แž„แž–แžธแž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžŸแŸ’แžœแŸแž™แž”แŸ’แžšแžœแžแŸ’แžแžทแž’แŸ’แžœแžพแžฑแŸ’แž™แž‡แžธแžœแžทแžแž›แŸ†แž”แžถแž€แžŸแž˜แŸ’แžšแžถแž”แŸ‹แžขแŸ’แž“แž€แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แžŠแŸƒแŸ”

    แžขแŸ’แž“แž€แžแŸ’แž›แŸ‡แž“แžนแž„แž“แžทแž™แžถแž™แžแžถ แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžŸแŸ’แžœแŸแž™แž”แŸ’แžšแžœแžแŸ’แžแžทแž›แŸ’แžขแž‚แžฝแžšแžแŸ‚แžŸแž˜แŸ’แžขแžถแžแž‘แžทแž“แŸ’แž“แž“แŸแž™แž”แž“แŸ’แž‘แžถแž”แŸ‹แž–แžธแžแŸ’แž›แžฝแž“แž‚แŸแŸ” แžแŸ’แž‰แžปแŸ†แž˜แžถแž“แžขแŸ†แžŽแŸ‡แžขแŸ†แžŽแžถแž„แž”แŸ’แžšแž†แžถแŸ†แž„แž“แžนแž„แŸ–

    • แž‡แŸ†แž แžšแžแžถแž˜แžœแž“แŸ’แžแž‚แžบแž„แžถแž™แžŸแŸ’แžšแžฝแž›แž”แŸ’แžšแžพแžŽแžถแžŸแŸ‹แŸ”
    • แž˜แžทแž“แž˜แŸ‚แž“แž‚แŸ’แžšแž”แŸ‹แžœแžแŸ’แžแžปแž‘แžถแŸ†แž„แžขแžŸแŸ‹แžขแžถแž…แžแŸ’แžšแžผแžœแž”แžถแž“แž™แž€แž…แŸแž‰แž–แžธแž”แŸ’แžšแž–แŸแž“แŸ’แž’แžแžถแž˜แžšแž™แŸˆ API แž“แŸ„แŸ‡แž‘แŸแŸ” แžงแž‘แžถแž แžšแžŽแŸ แž€แžถแžšแž แŸ…แžฑแŸ’แž™แž›แžปแž”แžœแžแŸ’แžแžปแž˜แžทแž“แžแŸ’แžšแžผแžœแž”แžถแž“แžขแž“แžปแžœแžแŸ’แžแž‘แŸ แž–แŸ’แžšแŸ„แŸ‡แžœแžถแž•แŸ’แž‘แžปแž™แž“แžนแž„แžแž€แŸ’แž€แžœแžทแž‡แŸ’แž‡แžถแžขแžถแž‡แžธแžœแž€แž˜แŸ’แž˜แŸ”
    • แž“แŸ…แž–แŸแž›แž”แž„แŸ’แž€แžพแžแžœแžแŸ’แžแžปแžแžถแž˜แžšแž™แŸˆ API แž‘แžทแž“แŸ’แž“แž“แŸแž™แž˜แŸแžแžถแž‡แžถแž…แŸ’แžšแžพแž“แžขแžถแž…แžแŸ’แžšแžผแžœแž”แžถแž“แž”แž„แŸ’แž€แžพแž แžŠแŸ‚แž›แž‡แžถแž”แž‰แŸ’แž แžถแž€แŸ’แž“แžปแž„แž€แžถแžšแž›แžปแž”แŸ”
    • แž”แŸ’แžšแžŸแžทแž“แž”แžพแž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแž˜แžถแž“แž—แžถแž–แžขแžถแžŸแŸ’แžšแŸแž™แž€แŸ’แž“แžปแž„แž…แŸ†แžŽแŸ„แž˜แž–แžฝแž€แž‚แŸ แž“แŸ„แŸ‡แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž“แŸƒแž€แžถแžšแžŸแž˜แŸ’แžขแžถแžแž‘แžทแž“แŸ’แž“แž“แŸแž™แž”แž“แŸ’แž‘แžถแž”แŸ‹แž–แžธแž€แžถแžšแžŠแŸ†แžŽแžพแžšแž€แžถแžšแž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแž”แŸ’แžšแŸ‚แž‘แŸ…แž‡แžถแžˆแžบแž€แŸ’แž”แžถแž›แŸ”
    • แž”แž“แŸ’แžแŸ‚แž˜ (แž แžพแž™แžแžถแž˜แž‚แŸ†แž“แžทแžแžšแž”แžŸแŸ‹แžแŸ’แž‰แžปแŸ† แž˜แžทแž“แžŸแž˜แž แŸแžแžปแž•แž›) แž แŸ…แž‘แŸ… API แŸ”
    • แž แžพแž™แžขแžถแž‚แžปแž™แž˜แŸ‰แž„แŸ‹แž…แž˜แŸ’แž”แž„: แž“แŸ…แž–แŸแž›แžŠแŸ‚แž›แž‘แžทแž“แŸ’แž“แž“แŸแž™แžŸแžถแž€แž›แŸ’แž”แž„แž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แžแŸ’แžšแžผแžœแž”แžถแž“แž‡แž˜แŸ’แžšแŸ‡แžŠแŸ„แž™แž•แŸ’แž‘แžถแž›แŸ‹แž–แžธแž˜แžผแž›แžŠแŸ’แž‹แžถแž“แž‘แžทแž“แŸ’แž“แž“แŸแž™แŸ” แž“แŸแŸ‡แž”แŸ’แžšแŸ‚แž‘แŸ…แž‡แžถแžŸแŸ€แž€ PK/FK แž–แžทแžแž”แŸ’แžšแžถแž€แžŠ! แž™แžพแž„แžฎแž–แžธแžขแŸ’แž“แž€แžขแž—แžทแžœแžŒแŸ’แžแž“แŸแŸ– "แžแŸ’แž‰แžปแŸ†แž‘แžพแž”แžแŸ‚แž”แžถแž“แž”แž“แŸ’แžแŸ‚แž˜/แžŠแž€แž…แŸแž‰/แž”แŸ’แžแžผแžšแžˆแŸ’แž˜แŸ„แŸ‡แžŸแž‰แŸ’แž‰แžถ แž แŸแžแžปแžขแŸ’แžœแžธแž”แžถแž“แž‡แžถแž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž› 100500 แž…แžถแž”แŸ‹แž”แžถแž“?"

    แžแžถแž˜แž‚แŸ†แž“แžทแžแžšแž”แžŸแŸ‹แžแŸ’แž‰แžปแŸ† แžŠแŸ†แžŽแŸ„แŸ‡แžŸแŸ’แžšแžถแž™แžŠแŸแž”แŸ’แžšแžŸแžพแžšแž”แŸ†แž•แžปแžแž‚แžบแž”แžšแžทแž™แžถแž€แžถแžŸแžแžถแž˜แžœแž“แŸ’แžแŸ”

  2. แž˜แž“แžปแžŸแŸ’แžŸแž‡แžถแž…แŸ’แžšแžพแž“แž”แŸ’แžšแžพ docker-compose แžŠแžพแž˜แŸ’แž”แžธแžŠแŸ†แžŽแžพแžšแž€แžถแžšแž”แžšแžทแž™แžถแž€แžถแžŸแžŸแžถแž€แž›แŸ’แž”แž„ แž”แŸ‰แžปแž“แŸ’แžแŸ‚แž˜แžถแž“แž˜แž“แžปแžŸแŸ’แžŸแžแžทแž…แžŽแžถแžŸแŸ‹แžŠแŸ‚แž›แž”แŸ’แžšแžพ docker-compose แž“แŸ…แž–แŸแž›แž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแž€แžถแžšแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž›แž“แŸ…แž€แŸ’แž“แžปแž„ CI/CD แŸ” แž แžพแž™แž“แŸ…แž‘แžธแž“แŸแŸ‡แžแŸ’แž‰แžปแŸ†แž˜แžทแž“แž™แž€แž‘แŸ…แž€แŸ’แž“แžปแž„แž‚แžŽแž“แžธ kubernetes, swarm แž“แžทแž„แžœแŸแž‘แžทแž€แžถ orchestration แž€แžปแž„แžแžบแž“แŸแžšแž•แŸ’แžŸแŸแž„แž‘แŸ€แžแž‘แŸแŸ” แž˜แžทแž“แž˜แŸ‚แž“แž‚แŸ’แžšแž”แŸ‹แž€แŸ’แžšแžปแž˜แž แŸŠแžปแž“แž‘แžถแŸ†แž„แžขแžŸแŸ‹แžŸแžปแž‘แŸ’แž’แžแŸ‚แž˜แžถแž“แž–แžฝแž€แž‚แŸแž‘แŸแŸ” แžœแžถแž›แŸ’แžขแž”แŸ’แžšแžŸแžทแž“แž”แžพ docker-compose.yml แž‡แžถแžŸแž€แž›แŸ”
  3. แž‘แŸ„แŸ‡แž”แžธแž‡แžถแž™แžพแž„แž˜แžถแž“แž€แž˜แŸ’แž˜แžœแžทแž’แžธแžšแžแŸ‹ QA แž•แŸ’แž‘แžถแž›แŸ‹แžšแž”แžŸแŸ‹แž™แžพแž„แž€แŸแžŠแŸ„แž™ แžแžพแž™แžพแž„แžขแžถแž…แž”แŸ’แžšแžถแž€แžŠแžแžถแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŠแŸ‚แž›แž”แžถแž“แžŠแŸ†แžŽแžพแžšแž€แžถแžšแžแžถแž˜แžšแž™แŸˆ docker-compose แž˜แžทแž“แž‡แŸ’แžšแŸ€แžแž‡แŸ’แžšแŸ‚แž€แž‚แŸ’แž“แžถแž‘แŸ…แžœแžทแž‰แž‘แŸ…แž˜แž€แžŠแŸ„แž™แžšแž”แŸ€แž”แžŽแžถ?
  4. แžแžพแž’แŸ’แžœแžพแžŠแžผแž…แž˜แŸ’แžแŸแž…แžŠแžพแž˜แŸ’แž”แžธแž”แŸ’แžšแž˜แžผแž›แž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŠแŸ‚แž›แž”แžถแž“แžŸแžถแž€แž›แŸ’แž”แž„?
  5. แžแžพแž’แŸ’แžœแžพแžŠแžผแž…แž˜แŸ’แžแŸแž…แžŠแžพแž˜แŸ’แž”แžธแžŸแž˜แŸ’แžขแžถแžแžขแŸ’แž“แž€แžšแžแŸ‹?

แžแŸ’แž‰แžปแŸ†แž˜แžถแž“แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab แž•แŸ’แž‘แžถแž›แŸ‹แžแŸ’แž›แžฝแž“แžšแž”แžŸแŸ‹แžแŸ’แž‰แžปแŸ†แžŸแž˜แŸ’แžšแžถแž”แŸ‹แž‚แž˜แŸ’แžšแŸ„แž„แžšแž”แžŸแŸ‹แžแŸ’แž‰แžปแŸ† แž แžพแž™แžแŸ’แž‰แžปแŸ†แž”แžถแž“แž‡แžฝแž”แž”แŸ’แžšแž‘แŸ‡แžŸแŸ†แžŽแžฝแžšแž‘แžถแŸ†แž„แž“แŸแŸ‡แž€แŸ’แž“แžปแž„แžขแŸ†แžกแžปแž„แž–แŸแž›แžขแž—แžทแžœแžŒแŸ’แžแž“แŸ แž˜แŸ‰แžถแžŸแŸŠแžธแž“แž—แŸ’แž‰แŸ€แžœ Java แžŸแž˜แŸ’แžšแžถแž”แŸ‹ TestRail. แž…แŸ’แž”แžถแžŸแŸ‹แž‡แžถแž„แž“แŸแŸ‡แž‘แŸ…แž‘แŸ€แž แž“แŸ…แž–แŸแž›แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž›แŸ” แžแžถแž„แž€แŸ’แžšแŸ„แž˜แž“แŸแŸ‡แž™แžพแž„แž“แžนแž„แžŠแŸ„แŸ‡แžŸแŸ’แžšแžถแž™แž”แž‰แŸ’แž แžถแž‘แžถแŸ†แž„แž“แŸแŸ‡แžŠแŸ„แž™แž”แŸ’แžšแžพแžงแž‘แžถแž แžšแžŽแŸแž–แžธแž‚แž˜แŸ’แžšแŸ„แž„แž“แŸแŸ‡แŸ”

แž‘แŸ…แž˜แžถแžแžทแž€แžถ

แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell

แžŸแž˜แŸ’แžšแžถแž”แŸ‹แžขแŸ’แž“แž€แžšแžแŸ‹แž”แŸ’แžšแžŽแžถแŸ†แž„ แžแŸ’แž‰แžปแŸ†แžŸแžผแž˜แžŽแŸ‚แž“แžถแŸ†แž˜แŸ‰แžถแžŸแŸŠแžธแž“แž“แžทแž˜แŸ’แž˜แžทแž Linux แžŠแŸ‚แž›แž˜แžถแž“ 4 vCPU, RAM 4 GB, HDD 50 GB แŸ”
แž˜แžถแž“แž–แŸแžแŸŒแž˜แžถแž“แž‡แžถแž…แŸ’แžšแžพแž“แžขแŸ†แž–แžธแž€แžถแžšแžŠแŸ†แžกแžพแž„ gitlab-runner แž“แŸ…แž›แžพแžขแŸŠแžธแž“แž’แžบแžŽแžทแž แžŠแžผแž…แŸ’แž“แŸแŸ‡แžŠแŸ„แž™แžŸแž„แŸ’แžแŸแž”แŸ–

  • แž…แžผแž›แž‘แŸ…แž˜แŸ‰แžถแžŸแŸŠแžธแž“แžแžถแž˜แžšแž™แŸˆ SSH
  • แž”แŸ’แžšแžŸแžทแž“แž”แžพแžขแŸ’แž“แž€แž˜แžถแž“ RAM แžแžทแž…แž‡แžถแž„ 8 GB แž“แŸ„แŸ‡แžแŸ’แž‰แžปแŸ†แžŸแžผแž˜แžŽแŸ‚แž“แžถแŸ† แž’แŸ’แžœแžพแž€แžถแžšแž•แŸ’แž›แžถแžŸแŸ‹แž”แŸ’แžแžผแžš 10 GBแžŠแžผแž…แŸ’แž“แŸแŸ‡แžแžถแžƒแžถแžแž€แžš OOM แž˜แžทแž“แž˜แž€แžŸแž˜แŸ’แž›แžถแž”แŸ‹แž—แžถแžšแž€แžทแž…แŸ’แž…แžšแž”แžŸแŸ‹แž™แžพแž„แžŠแŸ„แž™แžŸแžถแžšแžแŸ‚แžแŸ’แžœแŸ‡ RAM แŸ” แžœแžถแžขแžถแž…แž€แžพแžแžกแžพแž„แž“แŸ…แž–แŸแž›แžŠแŸ‚แž›แž€แžทแž…แŸ’แž…แž€แžถแžšแž…แŸ’แžšแžพแž“แž‡แžถแž„ 5 แžแŸ’แžšแžผแžœแž”แžถแž“แž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž€แŸ’แž“แžปแž„แž–แŸแž›แžŠแŸ†แžŽแžถแž›แž‚แŸ’แž“แžถแŸ” แž€แžถแžšแž„แžถแžšโ€‹แž“แžนแž„โ€‹แž˜แžถแž“โ€‹แžŠแŸ†แžŽแžพแžšโ€‹แž€แžถแžšโ€‹แž™แžบแžโ€‹แž‡แžถแž„โ€‹แž˜แžปแž“ แž”แŸ‰แžปแž“แŸ’แžแŸ‚โ€‹แž˜แžถแž“โ€‹แžŸแŸ’แžแžทแžšแž—แžถแž–แŸ”

    แžงแž‘แžถแž แžšแžŽแŸแž‡แžถแž˜แžฝแž™แžƒแžถแžแž€แžš OOM

    แž”แŸ’แžšแžŸแžทแž“แž”แžพแžขแŸ’แž“แž€แžƒแžพแž‰แž“แŸ…แž€แŸ’แž“แžปแž„แž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแž€แžทแž…แŸ’แž…แž€แžถแžš bash: line 82: 26474 Killedแž”แž“แŸ’แž‘แžถแž”แŸ‹แž˜แž€แž‚แŸ’แžšแžถแž“แŸ‹แžแŸ‚แž”แŸ’แžšแžแžทแž”แžแŸ’แžแžทแž›แžพแžขแŸ’แž“แž€แžšแžแŸ‹ sudo dmesg | grep 26474

    [26474]  1002 26474  1061935   123806     339        0             0 java
    Out of memory: Kill process 26474 (java) score 127 or sacrifice child
    Killed process 26474 (java) total-vm:4247740kB, anon-rss:495224kB, file-rss:0kB, shmem-rss:0kB

    แž แžพแž™โ€‹แž”แŸ’แžšแžŸแžทแž“แž”แžพโ€‹แžšแžผแž”แž—แžถแž–โ€‹แž˜แžพแž›แž‘แŸ…โ€‹แžŠแžผแž…โ€‹แž“แŸแŸ‡ แž“แŸ„แŸ‡โ€‹แžขแžถแž…โ€‹แž”แž“แŸ’แžแŸ‚แž˜ swap แžฌโ€‹แž”แž“แŸ’แžแŸ‚แž˜ RAMแŸ”

  • แžŠแŸ†แžกแžพแž„ แžขแŸ’แž“แž€แžšแžแŸ‹ gitlab, docker, docker- แžแŸ‚แž„, แž’แŸ’แžœแžพแŸ”
  • แž€แžถแžšแž”แž“แŸ’แžแŸ‚แž˜แžขแŸ’แž“แž€แž”แŸ’แžšแžพแž”แŸ’แžšแžถแžŸแŸ‹ gitlab-runner แž‘แŸ…แž€แŸ’แžšแžปแž˜ docker
    sudo groupadd docker
    sudo usermod -aG docker gitlab-runner
  • แž…แžปแŸ‡แžˆแŸ’แž˜แŸ„แŸ‡ แžขแŸ’แž“แž€แžšแžแŸ‹ gitlab แŸ”
  • แž”แžพแž€แžŸแž˜แŸ’แžšแžถแž”แŸ‹แž€แžถแžšแž€แŸ‚แžŸแž˜แŸ’แžšแžฝแž› /etc/gitlab-runner/config.toml แž“แžทแž„แž”แž“แŸ’แžแŸ‚แž˜

    concurrent=20
    [[runners]]
      request_concurrency = 10

    แžœแžถโ€‹แž“แžนแž„โ€‹แžขแž“แžปแž‰แŸ’แž‰แžถแžโ€‹แžฑแŸ’แž™โ€‹แžขแŸ’แž“แž€โ€‹แžŠแŸ†แžŽแžพแžšแž€แžถแžšโ€‹แž€แžทแž…แŸ’แž…แž€แžถแžšโ€‹แžŸแŸ’แžšแž”โ€‹แž‚แŸ’แž“แžถโ€‹แž›แžพโ€‹แžขแŸ’แž“แž€โ€‹แžšแžแŸ‹โ€‹แž˜แŸ’แž“แžถแž€แŸ‹แŸ” แžขแžถแž“โ€‹แž”แž“แŸ’แžแŸ‚แž˜ แž“แŸ…แž‘แžธแž“แŸแŸ‡.
    แž”แŸ’แžšแžŸแžทแž“แž”แžพแžขแŸ’แž“แž€แž˜แžถแž“แž˜แŸ‰แžถแžŸแŸŠแžธแž“แžŠแŸ‚แž›แž˜แžถแž“แžแžถแž˜แž–แž›แžแŸ’แž›แžถแŸ†แž„แž‡แžถแž„แžงแž‘แžถแž แžšแžŽแŸ 8 vCPU, RAM 16 GB แž“แŸ„แŸ‡แž›แŸแžแž‘แžถแŸ†แž„แž“แŸแŸ‡แžขแžถแž…แžแŸ’แžšแžผแžœแž”แžถแž“แž’แŸ’แžœแžพแžฑแŸ’แž™แž’แŸ†แž‡แžถแž„แž™แŸ‰แžถแž„แž แŸ„แž…แžŽแžถแžŸแŸ‹ 2 แžŠแž„แŸ” แž”แŸ‰แžปแž“แŸ’แžแŸ‚แžœแžถแž‘แžถแŸ†แž„แžขแžŸแŸ‹แž‚แžบแžขแžถแžŸแŸ’แžšแŸแž™แž›แžพแžขแŸ’แžœแžธแžŠแŸ‚แž›แž–แžทแžแž”แŸ’แžšแžถแž€แžŠแž“แžนแž„แžแŸ’แžšแžผแžœแž”แžถแž“แžŠแžถแž€แŸ‹แžฑแŸ’แž™แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž›แžพแžขแŸ’แž“แž€แžšแžแŸ‹แž”แŸ’แžšแžŽแžถแŸ†แž„แž“แŸแŸ‡ แž“แžทแž„แž€แŸ’แž“แžปแž„แž”แžšแžทแž˜แžถแžŽแžขแŸ’แžœแžธแŸ”

แžœแžถโ€‹แž‚แŸ’แžšแž”แŸ‹แž‚แŸ’แžšแžถแž“แŸ‹โ€‹แž แžพแž™แŸ”

แž‘แŸ…แž˜แžถแžแžทแž€แžถ

แž€แŸ†แž–แžปแž„แžšแŸ€แž”แž…แŸ† docker-compose.yml

แž—แžถแžšแž€แžทแž…แŸ’แž…แž…แž˜แŸ’แž”แž„แž‚แžบ docker-compose.yml แžŸแž€แž› แžŠแŸ‚แž›แžขแŸ’แž“แž€แžขแž—แžทแžœแžŒแŸ’แžแž“แŸ/แžขแŸ’แž“แž€แžŸแžถแž€แž›แŸ’แž”แž„แžขแžถแž…แž”แŸ’แžšแžพแž‘แžถแŸ†แž„แž€แŸ’แž“แžปแž„แžŸแŸ’แžšแžปแž€ แž“แžทแž„แž€แŸ’แž“แžปแž„แž”แŸ†แž–แž„แŸ‹ CI แŸ”

แž‡แžถแžŠแŸ†แž”แžผแž„ แž™แžพแž„แž”แž„แŸ’แž€แžพแžแžˆแŸ’แž˜แŸ„แŸ‡แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžแŸ‚แž˜แžฝแž™แž‚แžแŸ‹แžŸแž˜แŸ’แžšแžถแž”แŸ‹ CI แŸ” แžขแžแŸแžšแžแŸ‚แž˜แžฝแž™แž‚แžแŸ‹แž“แŸ…แž€แŸ’แž“แžปแž„ GitLab CI แž‚แžบแž‡แžถแžขแžแŸแžš CI_JOB_ID. แž”แŸ’แžšแžŸแžทแž“แž”แžพแžขแŸ’แž“แž€แž”แž‰แŸ’แž‡แžถแž€แŸ‹ container_name แž‡แžถแž˜แžฝแž™แž“แžนแž„แžขแžแŸ’แžแž“แŸแž™ "service-${CI_JOB_ID:-local}"แž”แž“แŸ’แž‘แžถแž”แŸ‹แž˜แž€แž€แŸ’แž“แžปแž„แž€แžšแžŽแžธแŸ–

  • แž”แŸ’แžšแžŸแžทแž“แž”แžพ CI_JOB_ID แž˜แžทแž“แžแŸ’แžšแžผแžœแž”แžถแž“แž€แŸ†แžŽแžแŸ‹แž“แŸ…แž€แŸ’แž“แžปแž„แžขแžแŸแžšแž”แžšแžทแžŸแŸ’แžแžถแž“,
    แž”แž“แŸ’แž‘แžถแž”แŸ‹แž˜แž€แžˆแŸ’แž˜แŸ„แŸ‡แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แž“แžนแž„แž˜แžถแž“ service-local
  • แž”แŸ’แžšแžŸแžทแž“แž”แžพ CI_JOB_ID แž€แŸ†แžŽแžแŸ‹แž€แŸ’แž“แžปแž„แžขแžแŸแžšแž”แžšแžทแžŸแŸ’แžแžถแž“ (แžงแž‘แžถแž แžšแžŽแŸ แŸกแŸขแŸฃ)
    แž”แž“แŸ’แž‘แžถแž”แŸ‹แž˜แž€แžˆแŸ’แž˜แŸ„แŸ‡แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แž“แžนแž„แž˜แžถแž“ service-123

แž‘แžธแž–แžธแžš แž™แžพแž„แž”แž„แŸ’แž€แžพแžแž”แžŽแŸ’แžแžถแž‰แžšแžฝแž˜แž˜แžฝแž™แžŸแž˜แŸ’แžšแžถแž”แŸ‹แžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŠแŸ‚แž›แž”แžถแž“แž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แŸ” แžœแžถแž•แŸ’แžแž›แŸ‹แžฑแŸ’แž™แž™แžพแž„แž“แžผแžœแž—แžถแž–แžฏแž€แŸ„แž€แž˜แŸ’แžšแžทแžแž”แžŽแŸ’แžแžถแž‰แž“แŸ…แž–แŸแž›แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž”แžšแžทแž™แžถแž€แžถแžŸแžŸแžถแž€แž›แŸ’แž”แž„แž…แŸ’แžšแžพแž“แŸ”

networks:
  default:
    external:
      name: service-network-${CI_JOB_ID:-local}

แžแžถแž˜แž–แžทแžแž“แŸแŸ‡แž‚แžบแž‡แžถแž‡แŸ†แž แžถแž“แžŠแŸ†แž”แžผแž„แžŠแžพแž˜แŸ’แž”แžธแž‡แŸ„แž‚แž‡แŸแž™ =)

แžงแž‘แžถแž แžšแžŽแŸแž“แŸƒ docker-compose.yml แžšแž”แžŸแŸ‹แžแŸ’แž‰แžปแŸ†แž‡แžถแž˜แžฝแž™แž“แžนแž„แž˜แžแžทแž™แŸ„แž”แž›แŸ‹

version: "3"

# ะ”ะปั ะบะพั€ั€ะตะบั‚ะฝะพะน ั€ะฐะฑะพั‚ั‹ web (php) ะธ fmt ะฝัƒะถะฝะพ, 
# ั‡ั‚ะพะฑั‹ ะบะพะฝั‚ะตะนะฝะตั€ั‹ ะธะผะตะปะธ ะพะฑั‰ะธะน ะธัะฟะพะปะฝัะตะผั‹ะน ะบะพะฝั‚ะตะฝั‚.
# ะ’ ะฝะฐัˆะตะผ ัะปัƒั‡ะฐะต, ัั‚ะพ ะดะธั€ะตะบั‚ะพั€ะธั /var/www/testrail
volumes:
  static-content:

# ะ˜ะทะพะปะธั€ัƒะตะผ ะพะบั€ัƒะถะตะฝะธะต ะฝะฐ ัะตั‚ะตะฒะพะผ ัƒั€ะพะฒะฝะต
networks:
  default:
    external:
      name: testrail-network-${CI_JOB_ID:-local}

services:
  db:
    image: mysql:5.7.22
    # ะšะฐะถะดั‹ะน container_name ัะพะดะตั€ะถะธั‚ ${CI_JOB_ID:-local}
    container_name: "testrail-mysql-${CI_JOB_ID:-local}"
    environment:
      MYSQL_HOST: db
      MYSQL_DATABASE: mydb
      MYSQL_ROOT_PASSWORD: 1234
      SKIP_GRANT_TABLES: 1
      SKIP_NETWORKING: 1
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    networks:
    - default

  migration:
    image: registry.gitlab.com/touchbit/image/testrail/migration:latest
    container_name: "testrail-migration-${CI_JOB_ID:-local}"
    links:
    - db
    depends_on:
    - db
    networks:
    - default

  fpm:
    image: registry.gitlab.com/touchbit/image/testrail/fpm:latest
    container_name: "testrail-fpm-${CI_JOB_ID:-local}"
    volumes:
    - static-content:/var/www/testrail
    links:
    - db
    networks:
    - default

  web:
    image: registry.gitlab.com/touchbit/image/testrail/web:latest
    container_name: "testrail-web-${CI_JOB_ID:-local}"
    # ะ•ัะปะธ ะฟะตั€ะตะผะตะฝะฝั‹ะต TR_HTTP_PORT ะธะปะธ TR_HTTPS_PORTS ะฝะต ะพะฟั€ะตะดะตะปะตะฝั‹,
    # ั‚ะพ ัะตั€ะฒะธั ะฟะพะดะฝะธะผะฐะตั‚ัั ะฝะฐ 80 ะธ 443 ะฟะพั€ั‚ัƒ ัะพะพั‚ะฒะตั‚ัั‚ะฒะตะฝะฝะพ.
    ports:
      - ${TR_HTTP_PORT:-80}:80
      - ${TR_HTTPS_PORT:-443}:443
    volumes:
      - static-content:/var/www/testrail
    links:
      - db
      - fpm
    networks:
      - default

แžงแž‘แžถแž แžšแžŽแŸแž“แŸƒแž€แžถแžšแžšแžแŸ‹แž€แŸ’แž“แžปแž„แžŸแŸ’แžšแžปแž€

docker-compose -f docker-compose.yml up -d
Starting   testrail-mysql-local     ... done
Starting   testrail-migration-local ... done
Starting   testrail-fpm-local       ... done
Recreating testrail-web-local       ... done

แž”แŸ‰แžปแž“แŸ’แžแŸ‚แž˜แžทแž“แž˜แŸ‚แž“แžขแŸ’แžœแžธแŸ—แž‘แžถแŸ†แž„แžขแžŸแŸ‹แž‚แžบแžŸแžถแž˜แž‰แŸ’แž‰แž‘แŸแž‡แžถแž˜แžฝแž™แž“แžนแž„แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž“แŸ…แž€แŸ’แž“แžปแž„ CI แŸ”

แž‘แŸ…แž˜แžถแžแžทแž€แžถ

แž€แŸ†แž–แžปแž„แžšแŸ€แž”แž…แŸ† Makefile

แžแŸ’แž‰แžปแŸ†แž”แŸ’แžšแžพ Makefile แž–แŸ’แžšแŸ„แŸ‡แžœแžถแž„แžถแž™แžŸแŸ’แžšแžฝแž›แžŽแžถแžŸแŸ‹แžŸแž˜แŸ’แžšแžถแž”แŸ‹แž€แžถแžšแž‚แŸ’แžšแž”แŸ‹แž‚แŸ’แžšแž„แž”แžšแžทแžŸแŸ’แžแžถแž“แž€แŸ’แž“แžปแž„แžแŸ†แž”แž“แŸ‹ แž“แžทแž„แž€แŸ’แž“แžปแž„ CI แŸ” แž™แŸ„แž”แž›แŸ‹แž›แžพแžขแŸŠแžธแž“แž’แžบแžŽแžทแžแž…แŸ’แžšแžพแž“แž‘แŸ€แž

# ะฃ ะผะตะฝั ะฒ ะฟั€ะพะตะบั‚ะฐั… ะฒัะต ะฒัะฟะพะผะพะณะฐั‚ะตะปัŒะฝั‹ะต ะฒะตั‰ะธ ะปะตะถะฐั‚ ะฒ ะดะธั€ะตะบั‚ะพั€ะธะธ `.indirect`,
# ะฒ ั‚ะพะผ ั‡ะธัะปะต ะธ `docker-compose.yml`

# ะ˜ัะฟะพะปัŒะทะพะฒะฐั‚ัŒ bash ั ะพะฟั†ะธะตะน pipefail 
# pipefail - ั„ะตะนะปะธั‚ ะฒั‹ะฟะพะปะฝะตะฝะธะต ะฟะฐะนะฟะฐ, ะตัะปะธ ะบะพะผะฐะฝะดะฐ ะฒั‹ะฟะพะปะฝะธะปะฐััŒ ั ะพัˆะธะฑะบะพะน
SHELL=/bin/bash -o pipefail

# ะžัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ะบะพะฝั‚ะตะนะฝะตั€ั‹ ะธ ัƒะดะฐะปัะตะผ ัะตั‚ัŒ
docker-kill:
    docker-compose -f $${CI_JOB_ID:-.indirect}/docker-compose.yml kill
    docker network rm network-$${CI_JOB_ID:-testrail} || true

# ะŸั€ะตะดะฒะฐั€ะธั‚ะตะปัŒะฝะพ ะฒั‹ะฟะพะปะฝัะตะผ docker-kill 
docker-up: docker-kill
    # ะกะพะทะดะฐะตะผ ัะตั‚ัŒ ะดะปั ะพะบั€ัƒะถะตะฝะธั 
    docker network create network-$${CI_JOB_ID:-testrail}
    # ะ—ะฐะฑะธั€ะฐะตะผ ะฟะพัะปะตะดะฝะธะต ะพะฑั€ะฐะทั‹ ะธะท docker-registry
    docker-compose -f $${CI_JOB_ID:-.indirect}/docker-compose.yml pull
    # ะ—ะฐะฟัƒัะบะฐะตะผ ะพะบั€ัƒะถะตะฝะธะต
    # force-recreate - ะฟั€ะธะฝัƒะดะธั‚ะตะปัŒะฝะพะต ะฟะตั€ะตัะพะทะดะฐะฝะธะต ะบะพะฝั‚ะตะนะฝะตั€ะพะฒ
    # renew-anon-volumes - ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ volumes ะฟั€ะตะดั‹ะดัƒั‰ะธั… ะบะพะฝั‚ะตะนะฝะตั€ะพะฒ
    docker-compose -f $${CI_JOB_ID:-.indirect}/docker-compose.yml up --force-recreate --renew-anon-volumes -d
    # ะัƒ ะธ, ะฝะฐ ะฒััะบะธะน ัะปัƒั‡ะฐะน, ะฒั‹ะฒะตัั‚ะธ ั‡ั‚ะพ ั‚ะฐะผ ัƒ ะฝะฐั ะฒ ะฟั€ะธะฝั†ะธะฟะต ะทะฐะฟัƒั‰ะตะฝะพ ะฝะฐ ะผะฐัˆะธะฝะบะต
    docker ps

# ะšะพะปะปะตะบั‚ะธะผ ะปะพะณะธ ัะตั€ะฒะธัะพะฒ
docker-logs:
    mkdir ./logs || true
    docker logs testrail-web-$${CI_JOB_ID:-local}       >& logs/testrail-web.log
    docker logs testrail-fpm-$${CI_JOB_ID:-local}       >& logs/testrail-fpm.log
    docker logs testrail-migration-$${CI_JOB_ID:-local} >& logs/testrail-migration.log
    docker logs testrail-mysql-$${CI_JOB_ID:-local}     >& logs/testrail-mysql.log

# ะžั‡ะธัั‚ะบะฐ ั€ะฐะฝะฝะตั€ะฐ
docker-clean:
    @echo ะžัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ะฒัะต testrail-ะบะพะฝั‚ะตะนะฝะตั€ั‹
    docker kill $$(docker ps --filter=name=testrail -q) || true
    @echo ะžั‡ะธัั‚ะบะฐ ะดะพะบะตั€ ะบะพะฝั‚ะตะนะฝะตั€ะพะฒ
    docker rm -f $$(docker ps -a -f --filter=name=testrail status=exited -q) || true
    @echo ะžั‡ะธัั‚ะบะฐ dangling ะพะฑั€ะฐะทะพะฒ
    docker rmi -f $$(docker images -f "dangling=true" -q) || true
    @echo ะžั‡ะธัั‚ะบะฐ testrail ะพะฑั€ะฐะทะพะฒ
    docker rmi -f $$(docker images --filter=reference='registry.gitlab.com/touchbit/image/testrail/*' -q) || true
    @echo ะžั‡ะธัั‚ะบะฐ ะฒัะตั… ะฝะตะธัะฟะพะปัŒะทัƒะตะผั‹ั… volume
    docker volume rm -f $$(docker volume ls -q) || true
    @echo ะžั‡ะธัั‚ะบะฐ ะฒัะตั… testrail ัะตั‚ะตะน
    docker network rm $(docker network ls --filter=name=testrail -q) || true
    docker ps

แž–แžทแž“แžทแžแŸ’แž™

แž”แž„แŸ’แž€แžพแž docker-up

$ make docker-up 
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml kill
Killing testrail-web-local   ... done
Killing testrail-fpm-local   ... done
Killing testrail-mysql-local ... done
docker network rm network-${CI_JOB_ID:-testrail} || true
network-testrail
docker network create network-${CI_JOB_ID:-testrail}
d2ec063324081c8bbc1b08fd92242c2ea59d70cf4025fab8efcbc5c6360f083f
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml pull
Pulling db        ... done
Pulling migration ... done
Pulling fpm       ... done
Pulling web       ... done
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml up --force-recreate --renew-anon-volumes -d
Recreating testrail-mysql-local ... done
Recreating testrail-fpm-local       ... done
Recreating testrail-migration-local ... done
Recreating testrail-web-local       ... done
docker ps
CONTAINER ID  PORTS                                     NAMES
a845d3cb0e5a  0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp  testrail-web-local
19d8ef001398  9000/tcp                                  testrail-fpm-local
e28840a2369c  3306/tcp, 33060/tcp                       testrail-migration-local
0e7900c23f37  3306/tcp                                  testrail-mysql-local

แž”แž„แŸ’แž€แžพแž docker-logs

$ make docker-logs
mkdir ./logs || true
mkdir: cannot create directory โ€˜./logsโ€™: File exists
docker logs testrail-web-${CI_JOB_ID:-local}       >& logs/testrail-web.log
docker logs testrail-fpm-${CI_JOB_ID:-local}       >& logs/testrail-fpm.log
docker logs testrail-migration-${CI_JOB_ID:-local} >& logs/testrail-migration.log
docker logs testrail-mysql-${CI_JOB_ID:-local}     >& logs/testrail-mysql.log

แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แž‘แŸ…แž˜แžถแžแžทแž€แžถ

แž€แŸ†แž–แžปแž„แžšแŸ€แž”แž…แŸ† .gitlab-ci.yml

แž€แŸ†แž–แžปแž„แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž›

Integration:
  stage: test
  tags:
    - my-shell-runner
  before_script:
    # ะัƒั‚ะตะฝั‚ะธั„ะธั†ะธั€ัƒะตะผัั ะฒ registry
    - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
    # ะ“ะตะฝะตั€ะธั€ัƒะตะผ ะฟัะตะฒะดะพัƒะฝะธะบะฐะปัŒะฝั‹ะต TR_HTTP_PORT ะธ TR_HTTPS_PORT
    - export TR_HTTP_PORT=$(shuf -i10000-60000 -n1)
    - export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1)
    # ัะพะทะดะฐะตะผ ะดะธั€ะตะบั‚ะพั€ะธัŽ ั ะธะดะตะฝั‚ะธั„ะธะบะฐั‚ะพั€ะพะผ ะทะฐะดะฐั‡ะธ
    - mkdir ${CI_JOB_ID}
    # ะบะพะฟะธั€ัƒะตะผ ะฒ ัะพะทะดะฐะฝะฝัƒัŽ ะดะธั€ะตะบั‚ะพั€ะธัŽ ะฝะฐัˆ docker-compose.yml
    # ั‡ั‚ะพะฑั‹ ะบะพะฝั‚ะตะบัั‚ ะฑั‹ะป ั€ะฐะทะฝั‹ะน ะดะปั ะบะฐะถะดะพะน ะทะฐะดะฐั‡ะธ
    - cp .indirect/docker-compose.yml ${CI_JOB_ID}/docker-compose.yml
  script:
    # ะฟะพะดะฝะธะผะฐะตะผ ะฝะฐัˆะต ะพะบั€ัƒะถะตะฝะธะต
    - make docker-up
    # ะทะฐะฟัƒัะบะฐะตะผ ั‚ะตัั‚ั‹ ะธัะฟะพะปะฝัะตะผั‹ะผ jar (ัƒ ะผะตะฝั ั‚ะฐะบ)
    - java -jar itest.jar --http-port ${TR_HTTP_PORT} --https-port ${TR_HTTPS_PORT}
    # ะธะปะธ ะฒ ะบะพะฝั‚ะตะนะฝะตั€ะต
    - docker run --network=testrail-network-${CI_JOB_ID:-local} --rm itest
  after_script:
    # ัะพะฑะธั€ะฐะตะผ ะปะพะณะธ
    - make docker-logs
    # ะพัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ะพะบั€ัƒะถะตะฝะธะต
    - make docker-kill
  artifacts:
    # ัะพั…ั€ะฐะฝัะตะผ ะปะพะณะธ
    when: always
    paths:
      - logs
    expire_in: 30 days

แž‡แžถแž›แž‘แŸ’แž’แž•แž›แž“แŸƒแž€แžถแžšแžŠแŸ†แžŽแžพแžšแž€แžถแžšแž€แžทแž…แŸ’แž…แž€แžถแžšแž”แŸ‚แž”แž“แŸแŸ‡ แžแžแžฏแž€แžŸแžถแžšแž€แŸ’แž“แžปแž„แžœแžแŸ’แžแžปแž”แžปแžšแžถแžŽแž“แžนแž„แž˜แžถแž“แžŸแŸแžœแžถแž€แž˜แŸ’แž˜ แž“แžทแž„แž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแžŸแžถแž€แž›แŸ’แž”แž„แŸ” แžŠแŸ‚แž›แž˜แžถแž“แž—แžถแž–แž„แžถแž™แžŸแŸ’แžšแžฝแž›แž€แŸ’แž“แžปแž„แž€แžšแžŽแžธแž˜แžถแž“แž€แŸ†แž แžปแžŸแŸ” แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแž“แžธแž˜แžฝแž™แŸ—แžŸแŸ’แžšแž”แž‚แŸ’แž“แžถแž“แžนแž„แžŸแžšแžŸแŸแžšแž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแž•แŸ’แž‘แžถแž›แŸ‹แžแŸ’แž›แžฝแž“แžšแž”แžŸแŸ‹แžœแžถ แž”แŸ‰แžปแž“แŸ’แžแŸ‚แžแŸ’แž‰แžปแŸ†แž“แžนแž„แž“แžทแž™แžถแž™แžขแŸ†แž–แžธแžšแžฟแž„แž“แŸแŸ‡แžŠแŸ„แž™แžกแŸ‚แž€แž–แžธแž‚แŸ’แž“แžถแŸ”

แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แž‘แŸ…แž˜แžถแžแžทแž€แžถ

แž€แžถแžšแžŸแž˜แŸ’แžขแžถแžแžขแŸ’แž“แž€แžšแžแŸ‹

แž€แžทแž…แŸ’แž…แž€แžถแžšโ€‹แž“แžนแž„โ€‹แžแŸ’แžšแžผแžœโ€‹แž”แžถแž“โ€‹แžŠแžถแž€แŸ‹โ€‹แžฑแŸ’แž™โ€‹แžŠแŸ†แžŽแžพแžšแž€แžถแžšโ€‹แžแŸ‚โ€‹แžแžถแž˜โ€‹แž€แžถแž›แžœแžทแž—แžถแž‚โ€‹แž”แŸ‰แžปแžŽแŸ’แžŽแŸ„แŸ‡แŸ”

stages:
- clean
- build
- test

Clean runner:
  stage: clean
  only:
    - schedules
  tags:
    - my-shell-runner
  script:
    - make docker-clean

แž”แž“แŸ’แž‘แžถแž”แŸ‹แž˜แž€ แžŸแžผแž˜แž…แžผแž›แž‘แŸ…แž€แžถแž“แŸ‹แž‚แž˜แŸ’แžšแŸ„แž„ GitLab แžšแž”แžŸแŸ‹แž™แžพแž„ -> CI/CD -> Schedules -> New Schedule แž แžพแž™แž”แž“แŸ’แžแŸ‚แž˜แž€แžถแž›แžœแžทแž—แžถแž‚แžแŸ’แž˜แžธ

แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แž‘แŸ…แž˜แžถแžแžทแž€แžถ

แž›แž‘แŸ’แž’แž•แž›

แž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž€แžทแž…แŸ’แž…แž€แžถแžš 4 แž“แŸ…แž€แŸ’แž“แžปแž„ GitLab CI
แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แž“แŸ…แž€แŸ’แž“แžปแž„แž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแž“แŸƒแž€แžทแž…แŸ’แž…แž€แžถแžšแž…แžปแž„แž€แŸ’แžšแŸ„แž™แž‡แžถแž˜แžฝแž™แž“แžนแž„แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž› แž™แžพแž„แžƒแžพแž‰แž€แžปแž„แžแžบแž“แŸแžšแž–แžธแž€แžทแž…แŸ’แž…แž€แžถแžšแž•แŸ’แžŸแŸแž„แŸ—

CONTAINER ID  NAMES
c6b76f9135ed  testrail-web-204645172
01d303262d8e  testrail-fpm-204645172
2cdab1edbf6a  testrail-migration-204645172
826aaf7c0a29  testrail-mysql-204645172
6dbb3fae0322  testrail-web-204645084
3540f8d448ce  testrail-fpm-204645084
70fea72aa10d  testrail-mysql-204645084
d8aa24b2892d  testrail-web-204644881
6d4ccd910fad  testrail-fpm-204644881
685d8023a3ec  testrail-mysql-204644881
1cdfc692003a  testrail-web-204644793
6f26dfb2683e  testrail-fpm-204644793
029e16b26201  testrail-mysql-204644793
c10443222ac6  testrail-web-204567103
04339229397e  testrail-fpm-204567103
6ae0accab28d  testrail-mysql-204567103
b66b60d79e43  testrail-web-204553690
033b1f46afa9  testrail-fpm-204553690
a8879c5ef941  testrail-mysql-204553690
069954ba6010  testrail-web-204553539
ed6b17d911a5  testrail-fpm-204553539
1a1eed057ea0  testrail-mysql-204553539

แž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแž›แž˜แŸ’แžขแžทแžแž”แž“แŸ’แžแŸ‚แž˜แž‘แŸ€แž

$ docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/gitlab-runner/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
$ export TR_HTTP_PORT=$(shuf -i10000-60000 -n1)
$ export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1)
$ mkdir ${CI_JOB_ID}
$ cp .indirect/docker-compose.yml ${CI_JOB_ID}/docker-compose.yml
$ make docker-up
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml kill
docker network rm testrail-network-${CI_JOB_ID:-local} || true
Error: No such network: testrail-network-204645172
docker network create testrail-network-${CI_JOB_ID:-local}
0a59552b4464b8ab484de6ae5054f3d5752902910bacb0a7b5eca698766d0331
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml pull
Pulling web       ... done
Pulling fpm       ... done
Pulling migration ... done
Pulling db        ... done
docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml up --force-recreate --renew-anon-volumes -d
Creating volume "204645172_static-content" with default driver
Creating testrail-mysql-204645172 ... 
Creating testrail-mysql-204645172 ... done
Creating testrail-migration-204645172 ... done
Creating testrail-fpm-204645172       ... done
Creating testrail-web-204645172       ... done
docker ps
CONTAINER ID        IMAGE                                                          COMMAND                  CREATED              STATUS              PORTS                                           NAMES
c6b76f9135ed        registry.gitlab.com/touchbit/image/testrail/web:latest         "nginx -g 'daemon ofโ€ฆ"   13 seconds ago       Up 1 second         0.0.0.0:51148->80/tcp, 0.0.0.0:25426->443/tcp   testrail-web-204645172
01d303262d8e        registry.gitlab.com/touchbit/image/testrail/fpm:latest         "docker-php-entrypoiโ€ฆ"   16 seconds ago       Up 13 seconds       9000/tcp                                        testrail-fpm-204645172
2cdab1edbf6a        registry.gitlab.com/touchbit/image/testrail/migration:latest   "docker-entrypoint.sโ€ฆ"   16 seconds ago       Up 13 seconds       3306/tcp, 33060/tcp                             testrail-migration-204645172
826aaf7c0a29        mysql:5.7.22                                                   "docker-entrypoint.sโ€ฆ"   18 seconds ago       Up 16 seconds       3306/tcp                                        testrail-mysql-204645172
6dbb3fae0322        registry.gitlab.com/touchbit/image/testrail/web:latest         "nginx -g 'daemon ofโ€ฆ"   36 seconds ago       Up 22 seconds       0.0.0.0:44202->80/tcp, 0.0.0.0:20151->443/tcp   testrail-web-204645084
3540f8d448ce        registry.gitlab.com/touchbit/image/testrail/fpm:latest         "docker-php-entrypoiโ€ฆ"   38 seconds ago       Up 35 seconds       9000/tcp                                        testrail-fpm-204645084
70fea72aa10d        mysql:5.7.22                                                   "docker-entrypoint.sโ€ฆ"   40 seconds ago       Up 37 seconds       3306/tcp                                        testrail-mysql-204645084
d8aa24b2892d        registry.gitlab.com/touchbit/image/testrail/web:latest         "nginx -g 'daemon ofโ€ฆ"   About a minute ago   Up 53 seconds       0.0.0.0:31103->80/tcp, 0.0.0.0:43872->443/tcp   testrail-web-204644881
6d4ccd910fad        registry.gitlab.com/touchbit/image/testrail/fpm:latest         "docker-php-entrypoiโ€ฆ"   About a minute ago   Up About a minute   9000/tcp                                        testrail-fpm-204644881
685d8023a3ec        mysql:5.7.22                                                   "docker-entrypoint.sโ€ฆ"   About a minute ago   Up About a minute   3306/tcp                                        testrail-mysql-204644881
1cdfc692003a        registry.gitlab.com/touchbit/image/testrail/web:latest         "nginx -g 'daemon ofโ€ฆ"   About a minute ago   Up About a minute   0.0.0.0:44752->80/tcp, 0.0.0.0:23540->443/tcp   testrail-web-204644793
6f26dfb2683e        registry.gitlab.com/touchbit/image/testrail/fpm:latest         "docker-php-entrypoiโ€ฆ"   About a minute ago   Up About a minute   9000/tcp                                        testrail-fpm-204644793
029e16b26201        mysql:5.7.22                                                   "docker-entrypoint.sโ€ฆ"   About a minute ago   Up About a minute   3306/tcp                                        testrail-mysql-204644793
c10443222ac6        registry.gitlab.com/touchbit/image/testrail/web:latest         "nginx -g 'daemon ofโ€ฆ"   5 hours ago          Up 5 hours          0.0.0.0:57123->80/tcp, 0.0.0.0:31657->443/tcp   testrail-web-204567103
04339229397e        registry.gitlab.com/touchbit/image/testrail/fpm:latest         "docker-php-entrypoiโ€ฆ"   5 hours ago          Up 5 hours          9000/tcp                                        testrail-fpm-204567103
6ae0accab28d        mysql:5.7.22                                                   "docker-entrypoint.sโ€ฆ"   5 hours ago          Up 5 hours          3306/tcp                                        testrail-mysql-204567103
b66b60d79e43        registry.gitlab.com/touchbit/image/testrail/web:latest         "nginx -g 'daemon ofโ€ฆ"   5 hours ago          Up 5 hours          0.0.0.0:56321->80/tcp, 0.0.0.0:58749->443/tcp   testrail-web-204553690
033b1f46afa9        registry.gitlab.com/touchbit/image/testrail/fpm:latest         "docker-php-entrypoiโ€ฆ"   5 hours ago          Up 5 hours          9000/tcp                                        testrail-fpm-204553690
a8879c5ef941        mysql:5.7.22                                                   "docker-entrypoint.sโ€ฆ"   5 hours ago          Up 5 hours          3306/tcp                                        testrail-mysql-204553690
069954ba6010        registry.gitlab.com/touchbit/image/testrail/web:latest         "nginx -g 'daemon ofโ€ฆ"   5 hours ago          Up 5 hours          0.0.0.0:32869->80/tcp, 0.0.0.0:16066->443/tcp   testrail-web-204553539
ed6b17d911a5        registry.gitlab.com/touchbit/image/testrail/fpm:latest         "docker-php-entrypoiโ€ฆ"   5 hours ago          Up 5 hours          9000/tcp                                        testrail-fpm-204553539
1a1eed057ea0        mysql:5.7.22                                                   "docker-entrypoint.sโ€ฆ"   5 hours ago          Up 5 hours          3306/tcp                                        testrail-mysql-204553539

แž€แžทแž…แŸ’แž…แž€แžถแžšแž‘แžถแŸ†แž„แžขแžŸแŸ‹แž”แžถแž“แž”แž‰แŸ’แž…แž”แŸ‹แžŠแŸ„แž™แž‡แŸ„แž‚แž‡แŸแž™

แžœแžแŸ’แžแžปแž”แžปแžšแžถแžŽแž“แŸƒแž€แžทแž…แŸ’แž…แž€แžถแžšแž˜แžถแž“แž•แŸ’แž‘แžปแž€แžŸแŸแžœแžถแž€แž˜แŸ’แž˜ แž“แžทแž„แž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแžŸแžถแž€แž›แŸ’แž”แž„
แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แžขแŸ’แžœแžธแŸ—แž แžถแž€แŸ‹แž”แžธแžŠแžผแž…แž‡แžถแžŸแŸ’แžšแžŸแŸ‹แžŸแŸ’แžขแžถแž แž”แŸ‰แžปแž“แŸ’แžแŸ‚แž˜แžถแž“แž—แžถแž–แžแžปแžŸแž”แŸ’แž›แŸ‚แž€แž‚แŸ’แž“แžถแŸ” แž”แŸ†แž–แž„แŸ‹แžขแžถแž…แžแŸ’แžšแžผแžœแž”แžถแž“แž›แžปแž”แž…แŸ„แž›แžŠแŸ„แž™แž”แž„แŸ’แžแŸ† แžแžŽแŸˆแž–แŸแž›แžŠแŸ‚แž›แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžšแžฝแž˜แž”แž‰แŸ’แž…แžผแž›แž€แŸ†แž–แžปแž„แžŠแŸ†แžŽแžพแžšแž€แžถแžš แž€แŸ’แž“แžปแž„แž€แžšแžŽแžธแž“แŸแŸ‡แž€แžปแž„แžแžบแž“แŸแžšแžŠแŸ‚แž›แž€แŸ†แž–แžปแž„แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž“แžนแž„แž˜แžทแž“แžแŸ’แžšแžผแžœแž”แžถแž“แž”แž‰แŸ’แžˆแž”แŸ‹แžกแžพแž™แŸ” แž–แžธแž–แŸแž›แž˜แžฝแž™แž‘แŸ…แž–แŸแž›แž˜แžฝแž™แžขแŸ’แž“แž€แžแŸ’แžšแžผแžœแžŸแž˜แŸ’แžขแžถแžแžขแŸ’แž“แž€แžšแžแŸ‹แŸ” แž‡แžถแžขแž€แžปแžŸแž› แž—แžถแžšแž€แžทแž…แŸ’แž…แžŸแž˜แŸ’แžšแžถแž”แŸ‹แž’แŸ’แžœแžพแžฑแŸ’แž™แž”แŸ’แžšแžŸแžพแžšแžกแžพแž„แž“แŸ…แž€แŸ’แž“แžปแž„ GitLab CE แž“แŸ…แžแŸ‚แžŸแŸ’แžแžทแžแž€แŸ’แž“แžปแž„แžŸแŸ’แžแžถแž“แž—แžถแž–แžŠแžŠแŸ‚แž› แž”แžพแž€แž‘แžผแž›แžถแž™

แž”แŸ‰แžปแž“แŸ’แžแŸ‚โ€‹แž™แžพแž„โ€‹แž”แžถแž“โ€‹แž”แž“แŸ’แžแŸ‚แž˜โ€‹แž€แžถแžšโ€‹แž…แžถแž”แŸ‹โ€‹แž•แŸ’แžŠแžพแž˜โ€‹แž€แžทแž…แŸ’แž…แž€แžถแžšโ€‹แž˜แžฝแž™โ€‹แžแžถแž˜โ€‹แž€แžถแž›แžœแžทแž—แžถแž‚ แž แžพแž™โ€‹แž‚แŸ’แž˜แžถแž“โ€‹แžขแŸ’แž“แž€โ€‹แžŽแžถโ€‹แž แžถแž˜โ€‹แž™แžพแž„โ€‹แžฒแŸ’แž™โ€‹แžŠแŸ†แžŽแžพแžšแž€แžถแžšโ€‹แžœแžถโ€‹แžŠแŸ„แž™โ€‹แžŠแŸƒโ€‹แžกแžพแž™แŸ”
แž…แžผแž›แž‘แŸ…แž€แžถแž“แŸ‹แž‚แž˜แŸ’แžšแŸ„แž„แžšแž”แžŸแŸ‹แž™แžพแž„ -> CI/CD -> Schedules แž แžพแž™แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž—แžถแžšแž€แžทแž…แŸ’แž… Clean runner

แžขแŸ’แž“แž€แžšแžแŸ‹ GitLab Shell แŸ” แž€แžถแžšแž…แžถแž”แŸ‹แž•แŸ’แžแžพแž˜แž”แŸ’แžšแž€แžฝแžแž”แŸ’แžšแž‡แŸ‚แž„แž“แŸƒแžŸแŸแžœแžถแž€แž˜แŸ’แž˜แžŸแžถแž€แž›แŸ’แž”แž„แžŠแŸ„แž™แž”แŸ’แžšแžพ Docker Compose

แžŸแžšแžปแž”:

  • แž™แžพแž„แž˜แžถแž“แžขแŸ’แž“แž€แžšแžแŸ‹แžŸแŸ‚แž›แž˜แŸ’แž“แžถแž€แŸ‹แŸ”
  • แž˜แžทแž“แž˜แžถแž“แž‡แž˜แŸ’แž›แŸ„แŸ‡แžšแžœแžถแž„แž€แžถแžšแž„แžถแžš แž“แžทแž„แž”แžšแžทแžŸแŸ’แžแžถแž“แž‘แŸแŸ”
  • แž™แžพแž„แžŠแŸ†แžŽแžพแžšแž€แžถแžšแž—แžถแžšแž€แžทแž…แŸ’แž…แž‡แžถแž˜แžฝแž™แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžŸแž˜แžถแž แžšแžŽแž€แž˜แŸ’แž˜แžŸแŸ’แžšแž”แž‚แŸ’แž“แžถแŸ”
  • แžขแŸ’แž“แž€โ€‹แžขแžถแž…โ€‹แžŠแŸ†แžŽแžพแžšแž€แžถแžšโ€‹แž€แžถแžšโ€‹แž’แŸ’แžœแžพโ€‹แžแŸแžŸแŸ’แžโ€‹แžŸแž˜แžถแž แžšแžŽแž€แž˜แŸ’แž˜โ€‹แž‘แžถแŸ†แž„โ€‹แž€แŸ’แž“แžปแž„โ€‹แž˜แžผแž›แžŠแŸ’แž‹แžถแž“ แžฌโ€‹แž€แŸ’แž“แžปแž„โ€‹แž€แžปแž„แžแžบแž“แŸแžšแŸ”
  • แž€แŸ†แžŽแžแŸ‹แž แŸแžแžปแžŸแŸแžœแžถแž€แž˜แŸ’แž˜ แž“แžทแž„แž€แžถแžšแž’แŸ’แžœแžพแžแŸแžŸแŸ’แžแžแŸ’แžšแžผแžœแž”แžถแž“แž”แŸ’แžšแž˜แžผแž› แž“แžทแž„แž—แŸ’แž‡แžถแž”แŸ‹แž‘แŸ…แž“แžนแž„แž€แžทแž…แŸ’แž…แž€แžถแžšแž”แŸ†แž–แž„แŸ‹แŸ”
  • แžœแžถแžขแžถแž…แž’แŸ’แžœแžพแž‘แŸ…แž”แžถแž“แžŠแžพแž˜แŸ’แž”แžธแžŸแž˜แŸ’แžขแžถแžแž€แž˜แŸ’แž˜แžœแžทแž’แžธแžšแžแŸ‹แž…แŸแž‰แž–แžธแžšแžผแž”แž—แžถแž– Docker แž…แžถแžŸแŸ‹แŸ”

แž–แŸแž›แžœแŸแž›แžถแžšแŸ€แž”แž…แŸ†แž‚แžบ ~ 2 แž˜แŸ‰แŸ„แž„แŸ”
แž“แŸ„แŸ‡แž แžพแž™แž‡แžถแž‘แžถแŸ†แž„แžขแžŸแŸ‹ แžแžถแž˜แž–แžทแžแŸ” แžแŸ’แž‰แžปแŸ†แž“แžนแž„แžšแžธแž€แžšแžถแž™แž€แŸ’แž“แžปแž„แž€แžถแžšแž‘แž‘แžฝแž›แž”แžถแž“แž˜แžแžทแž€แŸ‚แž›แž˜แŸ’แžขแŸ”

แž‘แŸ…แž˜แžถแžแžทแž€แžถ

แž”แŸ’แžšแž—แž–: www.habr.com

แž”แž“แŸ’แžแŸ‚แž˜แž˜แžแžทแž™แŸ„แž”แž›แŸ‹