diff --git a/.env b/.env index 0a007615..765165a0 100644 --- a/.env +++ b/.env @@ -25,6 +25,6 @@ REDIS_CHANNEL=log_channel #login details # USERNAME PASSWORD -admin Admin123 -hng HngTech -user Password +#admin Admin123 +#hng HngTech +#user Password diff --git a/README.md b/README.md index 678eb616..b369fae4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# HNG12 DevOps Stage3 Task +# HNG12 DevOps Stage4 Task This Repo Contains the code for a microservice application comprising of several components communicating to each other. In other words, this is an example of microservice. These microservices are written in different languages. diff --git a/acme.json b/acme.json new file mode 100644 index 00000000..e69de29b diff --git a/auth-api/Dockerfile b/auth-api/Dockerfile new file mode 100644 index 00000000..f17cbd4e --- /dev/null +++ b/auth-api/Dockerfile @@ -0,0 +1,28 @@ +FROM golang:1.20-alpine AS builder + +WORKDIR /app + +# Copy go mod and sum files +COPY auth-api/go.mod auth-api/go.sum ./ + +# Download dependencies +RUN go mod download + +# Copy source code +COPY auth-api/ . + +# Build the application +RUN CGO_ENABLED=0 GOOS=linux go build -o auth-api . + +# Use a small image for the final stage +FROM alpine:3.17 + +WORKDIR /app + +# Copy the binary from the builder stage +COPY --from=builder /app/auth-api . + +# Expose the port specified in .env +EXPOSE 8081 + +CMD ["./main"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..c2c7952e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,148 @@ +version: '3.8' + +services: + # Redis service + redis-queue: + image: redis:alpine + networks: + - backend + volumes: + - redis-data:/data + + # Frontend + frontend: + build: + context: . + dockerfile: frontend/Dockerfile + environment: + - PORT=8080 + - AUTH_API_ADDRESS=http://auth-api:8081 + - TODOS_API_ADDRESS=http://todos-api:8082 + labels: + - "traefik.enable=true" + - "traefik.http.routers.frontend.rule=Host(`samops.name.ng`)" + - "traefik.http.routers.frontend.entrypoints=websecure" + - "traefik.http.routers.frontend.tls.certresolver=myresolver" + networks: + - frontend + depends_on: + - auth-api + - todos-api + - users-api + + # Auth API + auth-api: + build: + context: . + dockerfile: auth-api/Dockerfile + environment: + - AUTH_API_PORT=8081 + - JWT_SECRET=myfancysecret + - USERS_API_ADDRESS=http://users-api:8083 + ports: + - "8081:8081" + labels: + - "traefik.enable=true" + - "traefik.http.routers.auth.rule=Host(`auth.samops.name.ng`) || (Host(`samops.name.ng`) && PathPrefix(`/api/auth`))" + - "traefik.http.routers.auth.entrypoints=websecure" + - "traefik.http.routers.auth.tls.certresolver=myresolver" + - "traefik.http.middlewares.auth-stripprefix.stripprefix.prefixes=/api/auth" + - "traefik.http.routers.auth.middlewares=auth-stripprefix@docker" + networks: + - frontend + - backend + depends_on: + - users-api + + # Todos API + todos-api: + build: + context: . + dockerfile: todos-api/Dockerfile + environment: + - JWT_SECRET=myfancysecret + - REDIS_HOST=redis-queue + - REDIS_PORT=6379 + - REDIS_CHANNEL=log_channel + ports: + - "8082:8082" + labels: + - "traefik.enable=true" + - "traefik.http.routers.todos.rule=Host(`todos.samops.name.ng`) || (Host(`samops.name.ng`) && PathPrefix(`/api/todos`))" + - "traefik.http.routers.todos.entrypoints=websecure" + - "traefik.http.routers.todos.tls.certresolver=myresolver" + - "traefik.http.middlewares.todos-stripprefix.stripprefix.prefixes=/api/todos" + - "traefik.http.routers.todos.middlewares=todos-stripprefix@docker" + networks: + - frontend + - backend + depends_on: + - redis-queue + - auth-api + + # Users API + users-api: + build: + context: . + dockerfile: users-api/Dockerfile + environment: + - SERVER_PORT=8083 + - JWT_SECRET=myfancysecret + ports: + - "8083:8083" + labels: + - "traefik.enable=true" + - "traefik.http.routers.users.rule=Host(`users.samops.name.ng`) || (Host(`samops.name.ng`) && PathPrefix(`/api/users`))" + - "traefik.http.routers.users.entrypoints=websecure" + - "traefik.http.routers.users.tls.certresolver=myresolver" + - "traefik.http.middlewares.users-stripprefix.stripprefix.prefixes=/api/users" + - "traefik.http.routers.users.middlewares=users-stripprefix@docker" + networks: + - frontend + - backend + + # Log Message Processor + log-processor: + build: + context: . + dockerfile: log-message-processor/Dockerfile + environment: + - REDIS_HOST=redis-queue + - REDIS_PORT=6379 + - REDIS_CHANNEL=log_channel + networks: + - backend + depends_on: + - redis-queue + + # Traefik as reverse proxy with SSL + traefik: + image: traefik:v2.9 + command: + - "--api.insecure=false" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web.address=:80" + - "--entrypoints.websecure.address=:443" + - "--certificatesresolvers.myresolver.acme.tlschallenge=true" + - "--certificatesresolvers.myresolver.acme.email=oyedejisamuel05@gmail.com" + - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" + # Redirect HTTP to HTTPS + - "--entrypoints.web.http.redirections.entryPoint.to=websecure" + - "--entrypoints.web.http.redirections.entryPoint.scheme=https" + ports: + - "80:80" + - "443:443" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "./letsencrypt:/letsencrypt" + networks: + - frontend + restart: always + +networks: + frontend: + backend: + +volumes: + redis-data: \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 00000000..d19490d9 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,28 @@ +FROM node:12 as build-stage + +WORKDIR /app + +# Copy package files and install dependencies +COPY frontend/package*.json ./ +RUN npm install + +# Copy project files and build +COPY frontend/ . +RUN npm run build + +# Production stage +FROM nginx:stable-alpine as production-stage +COPY --from=build-stage /app/dist /usr/share/nginx/html + +# Copy custom nginx configuration +COPY frontend/nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 8080 + +# Create a custom entrypoint script to run nginx on the specified port +RUN echo '#!/bin/sh\n\ +sed -i "s/listen 80/listen $PORT/g" /etc/nginx/conf.d/default.conf\n\ +nginx -g "daemon off;"' > /docker-entrypoint.sh && \ +chmod +x /docker-entrypoint.sh + +CMD ["/docker-entrypoint.sh"] \ No newline at end of file diff --git a/log-message-processor/Dockerfile b/log-message-processor/Dockerfile new file mode 100644 index 00000000..c1e0d968 --- /dev/null +++ b/log-message-processor/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.9-slim + +WORKDIR /app + +# Copy requirements file and install dependencies +COPY log-message-processor/requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy project files +COPY log-message-processor/ . + +CMD ["python", "main.py"] \ No newline at end of file diff --git a/todos-api/Dockerfile b/todos-api/Dockerfile new file mode 100644 index 00000000..54030a6e --- /dev/null +++ b/todos-api/Dockerfile @@ -0,0 +1,14 @@ +FROM node:12 + +WORKDIR /app + +# Copy package files and install dependencies +COPY package*.json ./ +RUN npm install + +# Copy project files +COPY todos-api/ . + +EXPOSE 8082 + +CMD ["npm", "server.js"] \ No newline at end of file diff --git a/users-api/Dockerfile b/users-api/Dockerfile new file mode 100644 index 00000000..ef2d68e2 --- /dev/null +++ b/users-api/Dockerfile @@ -0,0 +1,27 @@ +FROM maven:3.8.6-openjdk-11 AS build + +WORKDIR /app + +# Copy pom.xml +COPY users-api/pom.xml . + +# Download dependencies (this layer can be cached) +RUN mvn dependency:go-offline -B + +# Copy source code +COPY users-api/src ./src + +# Build the application +RUN mvn package -DskipTests + +# Final stage +FROM openjdk:11-jre-slim + +WORKDIR /app + +# Copy JAR from build stage +COPY --from=build /app/target/*.jar app.jar + +EXPOSE 8083 + +CMD ["java", "-jar", "app.jar"] \ No newline at end of file