소개 글 작성 배경 : 저희 팀에서 진행하는 스터디에 참여하는 멤버분들의 기술 포스팅 내용을 공유하고, 스터디 내용을 정리하기 위함

[일반 서버] Github Action + Ansible

목표 : 일반 서버에서 동작하는 애플리케이션을 대상으로 코드 업데이트 후 변경 반영 절차에 대한 CI/CD 파이프라인 구성

[kschoi]님 : 스터디 내용을 이해하기 쉽게 스샷으로 잘 정리해주셨습니다.

image.png

image.png

**name**: Run Ansible
**on**:
  workflow_dispatch:
  **push**:
    branches:
      - main

**jobs**:
  run-playbooks:
    runs-on: ubuntu-latest
    **steps**:
      - name: Github Repository Checkout
        uses: actions/checkout@v4

      - name: Setup Python 3
        uses: actions/setup-python@v5
        with:
          python-version: "3.8"

      - name: Upgrade Pip & Install Ansible
        run: |
          python -m pip install --upgrade pip
          python -m pip install ansible

      - name: Implement the Private SSH Key
        run: |
          mkdir -p ~/.ssh/
          echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa

      - name: Ansible Inventory File for Remote host
        run: |
          mkdir -p ./devops/ansible/
          export INVENTORY_FILE=./devops/ansible/inventory.ini
          echo "[my_host_group]" > $INVENTORY_FILE
          echo "${{ secrets.EC2_PIP }}" >> $INVENTORY_FILE

      - name: Ansible Default Configuration File
        run: |
          mkdir -p ./devops/ansible/
          cat <<EOF > ./devops/ansible/ansible.cfg
          [defaults]
          ansible_python_interpreter = '/usr/bin/python3'
          ansible_ssh_private_key_file = ~/.ssh/id_rsa
          remote_user = ubuntu
          inventory = ./inventory.ini
          host_key_checking = False
          EOF

      - name: Ping Ansible Hosts
        working-directory: ./devops/ansible/
        run: |
          ansible all -m ping

      # - name: Run Ansible Playbooks
      #   working-directory: ./devops/ansible/
      #   run: |
      #     ansible-playbook install-nginx.yaml

      # - name: Deploy Python via Ansible
      #   working-directory: ./devops/ansible/
      #   run: |
      #     ansible-playbook deploy-python.yaml

https://kschoi728.tistory.com/296

https://kschoi728.tistory.com/297

[daniel00324]님 : 실습 전체 내용을 따라하기 쉽게 정리해주셨습니다.

image.png

image.png

https://daniel00324.tistory.com/18

[hackjsp]님 : Self-hosted runner, Act(로컬 환경) 및 Ansible Playbook 실행, ArgoCD 파이프라인 등 정리해주셨습니다

image.png

image.png

...
jobs:
  run-playbooks:
    runs-on: self-hosted
    ...
     - name: Write Playbook
        run: |
          cat << EOF > ./devops/ansible/install-nginx.yaml
          ---
          - name: Install and Configure Nginx
            hosts: all
            become: yes # root 권한으로 실행
            tasks:
              - name: Update apt cache
                apt:
                  update_cache: yes

              - name: Install Nginx
                apt:
                  name: nginx
                  state: present

              - name: Start and Enable Nginx
                service:
                  name: nginx
                  state: started
                  enabled: yes

              - name: Check Nginx status
                shell: curl -I <http://localhost>
                register: nginx_status

              - name: Print Nginx status
                debug:
                  msg: "{{ nginx_status.stdout }}"
          EOF
      - name: Ping Ansible Hosts
        working-directory: ./devops/ansible/
        run: |
          ansible all -m ping

      - name: Run Ansible Playbooks
        working-directory: ./devops/ansible/
        run: |
          ansible-playbook install-nginx.yaml

[yu3papa]님 : Github Actions 관련 내용을 아주 상세하게 잘 정리해주셨습니다.

https://blog.naver.com/yu3papa/223696193234

[컨테이너] Jenkins + Docker

목표 : 컨테이너로 동작하는 애플리케이션을 대상으로 코드 업데이트 후 컨테이너 이미지 빌드 후 변경 반영 절차에 대한 CI/CD 파이프라인 구성

[kschoi]님 : 스터디 내용을 이해하기 쉽게 스샷으로 잘 정리해주셨습니다.

image.png

image.png

https://kschoi728.tistory.com/291

https://kschoi728.tistory.com/292

https://kschoi728.tistory.com/293

https://kschoi728.tistory.com/294

[daniel00324]님 : 실습 전체 내용을 따라하기 쉽게 정리해주셨습니다.

image.png

image.png

image.png

image.png

pipeline {
    agent any
    environment {
        DOCKER_IMAGE = '<자신의 도커 허브 계정>/dev-app' // Docker 이미지 이름
        CONTAINER_NAME = 'dev-app' // 컨테이너 이름
    }
    stages {
        stage('Checkout') {
            steps {
                 git branch: 'main',
                 url: '<http://192.168.254.124:3000/devops/dev-app.git>',  // Git에서 코드 체크아웃
                 credentialsId: 'gogs-dev-app'  // Credentials ID
            }
        }
        stage('Read VERSION') {
            steps {
                script {
                    // VERSION 파일 읽기
                    def version = readFile('VERSION').trim()
                    echo "Version found: ${version}"
                    // 환경 변수 설정
                    env.DOCKER_TAG = version
                }
            }
        }
        stage('Docker Build and Push') {
            steps {
                script {
                    docker.withRegistry('<https://index.docker.io/v1/>', 'dockerhub-credentials') {
                        // DOCKER_TAG 사용
                        def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
                        appImage.push()
                        appImage.push("latest")  // 빌드 이미지 push 할 때, 2개의 버전(현재 버전, latest 버전)을 업로드
                    }
                }
            }
        }
        stage('Check, Stop and Run Docker Container') {
            steps {
                script {
                    // 실행 중인 컨테이너 확인
                    def isRunning = sh(
                        script: "docker ps -q -f name=${CONTAINER_NAME}",
                        returnStdout: true
                    ).trim()
                    
                    if (isRunning) {
                        echo "Container '${CONTAINER_NAME}' is already running. Stopping it..."
                        // 실행 중인 컨테이너 중지
                        sh "docker stop ${CONTAINER_NAME}"
                        // 컨테이너 제거
                        sh "docker rm ${CONTAINER_NAME}"
                        echo "Container '${CONTAINER_NAME}' stopped and removed."
                    } else {
                        echo "Container '${CONTAINER_NAME}' is not running."
                    }
                    
                    // 5초 대기
                    echo "Waiting for 5 seconds before starting the new container..."
                    sleep(5)
                    
                    // 신규 컨테이너 실행
                    echo "Starting a new container '${CONTAINER_NAME}'..."
                    sh """
                    docker run -d --name ${CONTAINER_NAME} -p 4000:80 ${DOCKER_IMAGE}:${DOCKER_TAG}
                    """
                }
            }
        }
    }
    post {
        success {
            echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
        }
        failure {
            echo "Pipeline failed. Please check the logs."
        }
    }
}

https://daniel00324.tistory.com/17

[hackjsp]님 : jib를 활용하여 젠킨스 파이프라인 구성하기

image.png

https://cloud.google.com/java/getting-started/jib?hl=ko

https://cloud.google.com/java/getting-started/jib?hl=ko

image.png

# 1. 설정파일
# build.gradle 
jib {
    from {
        image = '<빌드_베이스이미지>'
    }
    to {
        image = '<배포_이미지명>'
        auth {}
    }
    conatiner
    ...
}

# 2. 명령어
./gradlew :<모듈명>:jib \\
  -Djib.from.image=<빌드_베이스이미지> \\
  -Djib.to.image=<배포_이미지명> 
  ...

https://hackjsp.tistory.com/71