diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..fb70131 --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,18 @@ +name: cicd-workflow with slack integration +on: + push: + branches: [ "master" ] +jobs: + job1: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build Docker image + run: | + docker build -t my-docker-repo . + - name: Run Trivy Scan + uses: aquasecurity/trivy-action@master + with: + image-ref: 'my-docker-repo:latest' + format: 'table' + severity: 'CRITICAL,HIGH' diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index eac633f..0000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -jobs: - - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) diff --git a/.github/workflows/github-actions-demo.yml b/.github/workflows/github-actions-demo.yml deleted file mode 100644 index 7d304f4..0000000 --- a/.github/workflows/github-actions-demo.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Om GitHub Actions Demo -on: - push: - branches: ["master"] - -jobs: - Explore-GitHub-Actions: - runs-on: ubuntu-latest - steps: - - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!" - - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." - - name: Check out repository code - uses: actions/checkout@v4 - - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - - run: echo "🖥️ The workflow is now ready to test your code on the runner." - - name: List files in the repository - run: | - ls ${{ github.workspace }} - - run: echo "🍏 This job's status is ${{ job.status }}." diff --git a/Dockerfile b/Dockerfile index a1402d6..7cf14e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,17 @@ -# this is my base image -FROM alpine:3.5 +# Use the official Python image from the Docker Hub with an Alpine variant +FROM python:3.9-alpine -# Install python and pip -RUN apk add --update py2-pip +# Set the working directory in the container +WORKDIR /app -# install Python modules needed by the Python app COPY requirements.txt /usr/src/app/ RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt # copy files required for the app to run COPY app.py /usr/src/app/ + COPY templates/index.html /usr/src/app/templates/ -# tell the port number the container should expose EXPOSE 5000 # run the application diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4e18362..0b288fe 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,5 +1,5 @@ # Docker -# Build a Docker image +# Build and push an image to Azure Container Registry # https://docs.microsoft.com/azure/devops/pipelines/languages/docker trigger: @@ -9,30 +9,60 @@ resources: - repo: self variables: + # Container registry service connection established during pipeline creation + dockerRegistryServiceConnection: 'd676875f-d1fb-485a-8da4-88d6bfb04604' + imageRepository: 'mypythondockerrepo' + containerRegistry: 'myacrrep31.azurecr.io' + dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile' tag: '$(Build.BuildId)' + vmImageName: 'ubuntu-latest' + stages: - stage: Build - displayName: Build image + displayName: Build and push stage jobs: - job: Build displayName: Build pool: - vmImage: ubuntu-latest + vmImage: $(vmImageName) steps: - task: Docker@2 - displayName: Build an image + displayName: Build Docker image inputs: - containerRegistry: 'Art_Docker' command: build - dockerfile: '$(Build.SourcesDirectory)/Dockerfile' - repository: $(repoName) + repository: $(imageRepository) + dockerfile: $(dockerfilePath) + containerRegistry: $(dockerRegistryServiceConnection) + tags: | + $(tag) + # Install Trivy Scanner on Agent + - task: Bash@3 + displayName: "Install Trivy" + inputs: + targetType: inline + script: | + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh + # Run Trivy Scan + - task: Bash@3 + displayName: "Run Trivy Scan" + inputs: + targetType: inline + script: | + ./bin/trivy image --severity HIGH,CRITICAL,MEDIUM --ignore-unfixed $(containerRegistry)/$(imageRepository):$(tag) + - task: Docker@2 + displayName: push Docker image to container registry + inputs: + command: push + repository: $(imageRepository) + dockerfile: $(dockerfilePath) + containerRegistry: $(dockerRegistryServiceConnection) tags: | $(tag) - - task: ArtifactoryDocker@1 + #Publish Build Information + - task: Bash@3 + displayName: "Log Image Details" inputs: - command: 'push' - artifactoryService: 'Art_SVC_conn' - targetRepo: '$(repoName)' - imageName: '$(imageName):$(tag)' - \ No newline at end of file + targetType: inline + script: | + echo "Pushed Image: $(containerRegistry)/$(imageRepository):$(tag)" \ No newline at end of file diff --git a/eks-deploy-from-ecr.yaml b/eks-deploy-from-ecr.yaml index 5801eaa..e1572df 100644 --- a/eks-deploy-from-ecr.yaml +++ b/eks-deploy-from-ecr.yaml @@ -2,8 +2,9 @@ apiVersion: apps/v1 kind: Deployment metadata: name: my-python-app-deployment + namespace: python-app-ns # Namespace where the deployment will be created spec: - replicas: 5 + replicas: 3 selector: matchLabels: app: python-app @@ -14,7 +15,7 @@ spec: spec: containers: - name: my-python-app - image: 211223789150.dkr.ecr.us-east-1.amazonaws.com/my-python-repo + image: 211223789150.dkr.ecr.us-east-1.amazonaws.com/devopscoach/my-python-repo:${BUILD_NUMBER} imagePullPolicy: Always ports: - containerPort: 5000 @@ -24,6 +25,7 @@ apiVersion: v1 kind: Service metadata: name: python-app-svc + namespace: python-app-ns # Namespace where the deployment will be created spec: selector: app: python-app @@ -31,4 +33,4 @@ spec: - protocol: TCP port: 80 targetPort: 5000 - type: LoadBalancer + type: ClusterIP diff --git a/ingress.yaml b/ingress.yaml new file mode 100644 index 0000000..152119e --- /dev/null +++ b/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: my-app-ingress + namespace: python-app-ns # Namespace where the deployment will be created + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: python-app-svc + port: + number: 80 diff --git a/k8s-deployment.yaml b/k8s-deployment.yaml index 51c3dc1..35c85f5 100644 --- a/k8s-deployment.yaml +++ b/k8s-deployment.yaml @@ -1,7 +1,8 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: my-python-deployment + name: my-python-app-deployment + namespace: python-app-ns # Namespace where the deployment will be created spec: replicas: 3 selector: @@ -14,7 +15,7 @@ spec: spec: containers: - name: my-python-app - image: akdevopscoaching/mypython-app + image: 211223789150.dkr.ecr.us-east-1.amazonaws.com/coachak/my-docker-repo:${BUILD_NUMBER} imagePullPolicy: Always ports: - containerPort: 5000 @@ -24,11 +25,12 @@ apiVersion: v1 kind: Service metadata: name: python-app-svc + namespace: python-app-ns # Namespace where the deployment will be created spec: selector: app: python-app ports: - protocol: TCP - port: 5000 + port: 80 targetPort: 5000 - type: LoadBalancer + type: ClusterIP diff --git a/requirements.txt b/requirements.txt index 632a1ef..08a66df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -Flask==0.10.1 +Flask==2.0.3 +Werkzeug==2.0.3 diff --git a/templates/index.html b/templates/index.html index ca5261a..5435f6a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,7 +3,7 @@