DEV Community

Cover image for How I Secured My Containerized Application Using Anchore (Day 29 Project)
Arbythecoder
Arbythecoder

Posted on

How I Secured My Containerized Application Using Anchore (Day 29 Project)

This article details a comprehensive approach to securing containerized applications using Anchore,
a container security platform. This project demonstrates a robust security workflow suitable for beginners, intermediate users,
and experienced developers. We'll cover building, testing, scanning, and deploying a containerized application, emphasizing best practices throughout. While Anchore is the focus, the principles apply to other container security tools like Aqua Security, Snyk, and Trivy.

1. Project Overview:

This project integrates security scanning into a CI/CD pipeline using Anchore to ensure only secure container images are deployed.
The process involves:

  1. Development and Testing: Write, test, and refine application code.
  2. Containerization: Package the application into a Docker container.
  3. Security Scanning: Use Anchore to scan for vulnerabilities.
  4. Image Building and Pushing: Build the Docker image and push to a registry (e.g., Docker Hub) only if the scan passes.
  5. Deployment: Deploy the secure image to your target environment (e.g., Kubernetes cluster, minikube).

2. Setting up Anchore:

Before starting, you need an Anchore Enterprise instance (or a free trial). Install the Anchore CLI and configure it:

  1. Download and Install: Download the Anchore CLI from the official Anchore website. Installation instructions vary depending on your operating system.
  2. Account Creation: Create an Anchore account if you don't have one already.
  3. Authentication: Configure the CLI to authenticate with your Anchore account. This usually involves setting an API key or using other authentication methods as described in Anchore's documentation.
  4. (Optional) Policy Configuration: In the Anchore UI, you can define policies to specify vulnerability thresholds. This allows you to customize the severity level at which the scan will fail. For example, you might set a policy to fail the build if any high or critical vulnerabilities are found.

3. Project Setup and Folder Structure:

Create the project directory and files:

project-root/
├── Dockerfile
├── .github/
│   └── workflows/
│       └── ci.yml
├── src/
│   └── app.js
└── tests/
    └── app.test.js
Enter fullscreen mode Exit fullscreen mode

4. Application Code (src/app.js - Node.js):

A simple Node.js Express.js application:

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello from Day 28!');
});

app.listen(port, () => {
  console.log(`App listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

5. Testing (tests/app.test.js - Jest):

Using Jest for testing the / route:

const request = require('supertest');
const app = require('../src/app');

describe('GET /', () => {
  it('should respond with Hello from Day 28!', async () => {
    const response = await request(app).get('/');
    expect(response.status).toBe(200);
    expect(response.text).toBe('Hello from Day 28!');
  });
});
Enter fullscreen mode Exit fullscreen mode

6. Dockerfile:

This builds the Docker image:

FROM node:14-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
USER node
EXPOSE 3000
CMD ["node", "app.js"]
Enter fullscreen mode Exit fullscreen mode

7. CI/CD Pipeline with GitHub Actions (.github/workflows/ci.yml):

This workflow automates the build, test, and scan process:

name: CI/CD with Anchore Scan

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build Docker image
        run: docker build -t myapp:latest .
      - name: Run tests
        run: npm test
      - name: Add image to Anchore #Anchore CLI must be configured (see Section 2)
        run: anchore-cli image add myapp:latest
      - name: Wait for Anchore scan
        run: anchore-cli image wait myapp:latest
      - name: Check Anchore vulnerabilities
        run: anchore-cli image vuln myapp:latest all | grep -v 'OK'
        if: ${{ steps.CheckAnchoreVulnerabilities.outcome != 'success' }}
      - name: Push to Docker Hub (if successful) #Replace with your Docker Hub details
        run: docker push docker.io/[YOUR_DOCKERHUB_USERNAME]/myapp:latest
        if: ${{ steps.CheckAnchoreVulnerabilities.outcome == 'success' }}
Enter fullscreen mode Exit fullscreen mode

Remember: Replace [YOUR_DOCKERHUB_USERNAME] with your Docker Hub username. You'll need to configure your Anchore CLI credentials as a GitHub Actions secret (under your repository's settings).

8. Deployment (Minikube Example):

After a successful build and scan, deploy to minikube (or your Kubernetes cluster) using a deployment.yaml file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: docker.io/[YOUR_DOCKERHUB_USERNAME]/myapp:latest
        ports:
        - containerPort: 3000
Enter fullscreen mode Exit fullscreen mode

9. Troubleshooting:

  • Anchore CLI Issues: Ensure the CLI is correctly installed and configured. Check Anchore's documentation for troubleshooting.
  • Build Errors: Carefully review the Dockerfile and application code for errors.
  • Deployment Errors: Verify the deployment.yaml file and Kubernetes configuration.
  • Vulnerability Findings: Address vulnerabilities reported by Anchore by updating dependencies or applying patches.

10. Alternative Container Security Tools:

While Anchore is used here, other tools like Aqua Security, Snyk, and Trivy offer similar capabilities. Explore these alternatives based on your needs and preferences.

11. Conclusion:

This project demonstrates a secure approach to containerized application development. Integrating Anchore into your CI/CD pipeline is crucial for maintaining security. Remember to adapt the code and configurations to your specific needs and always prioritize security best practices.

Top comments (0)