From 27d1a12929203c934252fd286130629af108172b Mon Sep 17 00:00:00 2001 From: Vladimir Mikhalev <10498744+heyvaldemar@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:43:16 -0500 Subject: [PATCH] Ollama with Let's Encrypt Using Docker Compose --- .env | 7 +- .github/dependabot.yml | 11 ++ .../workflows/00-deployment-verification.yml | 74 +++++++----- README.md | 107 +++++++++++++----- ollama-traefik-letsencrypt-docker-compose.yml | 105 +++++++++-------- 5 files changed, 194 insertions(+), 110 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.env b/.env index 103a4e4..efb7ee3 100644 --- a/.env +++ b/.env @@ -1,7 +1,10 @@ # Traefik Variables -TRAEFIK_IMAGE_TAG=traefik:2.9 +TRAEFIK_IMAGE_TAG=traefik:3.2 +# Set the log level (DEBUG, INFO, WARN, ERROR) TRAEFIK_LOG_LEVEL=WARN -TRAEFIK_ACME_EMAIL=callvaldemar@gmail.com +# The email address used by Let's Encrypt for renewal notices +TRAEFIK_ACME_EMAIL=admin@example.com +# The hostname used to access the Traefik dashboard and to configure domain-specific rules TRAEFIK_HOSTNAME=traefik.ollama.heyvaldemar.net # Basic Authentication for Traefik Dashboard # Username: traefikadmin diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..90e05c4 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/00-deployment-verification.yml b/.github/workflows/00-deployment-verification.yml index 8171b03..2c94b91 100644 --- a/.github/workflows/00-deployment-verification.yml +++ b/.github/workflows/00-deployment-verification.yml @@ -12,39 +12,59 @@ jobs: deploy-and-test: runs-on: ubuntu-latest + env: + NETWORK_ONE: ollama-network + NETWORK_TWO: traefik-network + DOCKER_COMPOSE_FILE: ollama-traefik-letsencrypt-docker-compose.yml + APP_HOSTNAME: ollama.heyvaldemar.net + APP_TRAEFIK_HOSTNAME: traefik.ollama.heyvaldemar.net + COMPOSE_PROJECT_NAME: ollama + steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Create necessary Docker networks + run: | + docker network create $NETWORK_ONE || true + docker network create $NETWORK_TWO || true - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Start up services using Docker Compose + run: docker compose -f $DOCKER_COMPOSE_FILE -p $COMPOSE_PROJECT_NAME up -d - - name: Create necessary Docker networks - run: | - docker network create ollama-network || true - docker network create traefik-network || true + - name: Modify /etc/hosts for internal routing + run: | + echo "127.0.0.1 $APP_HOSTNAME" | sudo tee -a /etc/hosts + echo "127.0.0.1 $APP_TRAEFIK_HOSTNAME" | sudo tee -a /etc/hosts - - name: Start up services using Docker Compose - run: docker compose -f ollama-traefik-letsencrypt-docker-compose.yml up -d + - name: Print Docker Compose services status + run: docker ps - - name: Modify /etc/hosts for internal routing - run: | - echo "127.0.0.1 ollama.heyvaldemar.net" | sudo tee -a /etc/hosts - echo "127.0.0.1 traefik.ollama.heyvaldemar.net" | sudo tee -a /etc/hosts + - name: Wait for the application to be ready via Traefik + run: | + echo "Checking the routing and availability of the application via Traefik..." + timeout 5m bash -c 'while ! curl -fsSLk "https://$APP_HOSTNAME"; do \ + echo "Waiting for the application to be ready..."; \ + sleep 10; \ + done' - - name: Print Docker Compose services status - run: docker ps + - name: Wait for the Traefik dashboard to be ready + run: | + echo "Checking the routing and availability of the Traefik dashboard..." + timeout 5m bash -c 'while ! curl -fsSLk --write-out "%{http_code}" --output /dev/null "https://$APP_TRAEFIK_HOSTNAME" | grep -E "200|401"; do \ + echo "Waiting for the application to be ready..."; \ + sleep 10; \ + done' - - name: Wait for the application to be ready via Traefik - run: | - echo "Checking the routing and availability of application via Traefik..." - timeout 5m bash -c 'while ! curl -fsSLk "https://ollama.heyvaldemar.net"; do echo "Waiting for the application to be ready..."; sleep 10; done' + - name: Inspect Network Configuration + run: | + docker network inspect $NETWORK_ONE + docker network inspect $NETWORK_TWO - - name: Inspect Network Configuration - run: | - docker network inspect ollama-network - docker network inspect traefik-network + - name: Show container logs on failure + if: failure() + run: docker compose -f $DOCKER_COMPOSE_FILE -p $COMPOSE_PROJECT_NAME logs - - name: Shutdown Docker Compose services - if: always() - run: docker compose -f ollama-traefik-letsencrypt-docker-compose.yml down + - name: Shutdown Docker Compose services + if: always() + run: docker compose -f $DOCKER_COMPOSE_FILE -p $COMPOSE_PROJECT_NAME down diff --git a/README.md b/README.md index 53227c9..062af53 100644 --- a/README.md +++ b/README.md @@ -22,31 +22,82 @@ Deploy Ollama using Docker Compose: `docker compose -f ollama-traefik-letsencrypt-docker-compose.yml -p ollama up -d` -# Author - -I’m Vladimir Mikhalev, the [Docker Captain](https://www.docker.com/captains/vladimir-mikhalev/), but my friends can call me Valdemar. - -🌐 My [website](https://www.heyvaldemar.com/) with detailed IT guides\ -🎬 Follow me on [YouTube](https://www.youtube.com/channel/UCf85kQ0u1sYTTTyKVpxrlyQ?sub_confirmation=1)\ -🐦 Follow me on [Twitter](https://twitter.com/heyValdemar)\ -🎨 Follow me on [Instagram](https://www.instagram.com/heyvaldemar/)\ -🧡 Follow me on [Threads](https://www.threads.net/@heyvaldemar)\ -🐘 Follow me on [Mastodon](https://mastodon.social/@heyvaldemar)\ -🧊 Follow me on [Bluesky](https://bsky.app/profile/heyvaldemar.bsky.social)\ -🎸 Follow me on [Facebook](https://www.facebook.com/heyValdemarFB/)\ -πŸŽ₯ Follow me on [TikTok](https://www.tiktok.com/@heyvaldemar)\ -πŸ’» Follow me on [LinkedIn](https://www.linkedin.com/in/heyvaldemar/)\ -🐈 Follow me on [GitHub](https://github.com/heyvaldemar) - -# Communication - -πŸ‘Ύ Chat with IT pros on [Discord](https://discord.gg/AJQGCCBcqf)\ -πŸ“§ Reach me at ask@sre.gg - -# Give Thanks - -πŸ’Ž Support on [GitHub](https://github.com/sponsors/heyValdemar)\ -πŸ† Support on [Patreon](https://www.patreon.com/heyValdemar)\ -πŸ₯€ Support on [BuyMeaCoffee](https://www.buymeacoffee.com/heyValdemar)\ -πŸͺ Support on [Ko-fi](https://ko-fi.com/heyValdemar)\ -πŸ’– Support on [PayPal](https://www.paypal.com/paypalme/heyValdemarCOM) +## Author + +hey everyone, + +πŸ’Ύ I’ve been in the IT game for over 20 years, cutting my teeth with some big names like [IBM](https://www.linkedin.com/in/heyvaldemar/), [Thales](https://www.linkedin.com/in/heyvaldemar/), and [Amazon](https://www.linkedin.com/in/heyvaldemar/). These days, I wear the hat of a DevOps Consultant and Team Lead, but what really gets me going is Docker and container technology - I’m kind of obsessed! + +πŸ’› I have my own IT [blog](https://www.heyvaldemar.com/), where I’ve built a [community](https://discord.gg/AJQGCCBcqf) of DevOps enthusiasts who share my love for all things Docker, containers, and IT technologies in general. And to make sure everyone can jump on this awesome DevOps train, I write super detailed guides (seriously, they’re foolproof!) that help even newbies deploy and manage complex IT solutions. + +πŸš€ My dream is to empower every single person in the DevOps community to squeeze every last drop of potential out of Docker and container tech. + +🐳 As a [Docker Captain](https://www.docker.com/captains/vladimir-mikhalev/), I’m stoked to share my knowledge, experiences, and a good dose of passion for the tech. My aim is to encourage learning, innovation, and growth, and to inspire the next generation of IT whizz-kids to push Docker and container tech to its limits. + +Let’s do this together! + +## My 2D Portfolio + +πŸ•ΉοΈ Click into [sre.gg](https://www.sre.gg/) β€” my virtual space is a 2D pixel-art portfolio inviting you to interact with elements that encapsulate the milestones of my DevOps career. + +## My Courses + +πŸŽ“ Dive into my [comprehensive IT courses](https://www.heyvaldemar.com/courses/) designed for enthusiasts and professionals alike. Whether you're looking to master Docker, conquer Kubernetes, or advance your DevOps skills, my courses provide a structured pathway to enhancing your technical prowess. + +πŸ”‘ [Each course](https://www.udemy.com/user/heyvaldemar/) is built from the ground up with real-world scenarios in mind, ensuring that you gain practical knowledge and hands-on experience. From beginners to seasoned professionals, there's something here for everyone to elevate their IT skills. + +## My Services + +πŸ’Ό Take a look at my [service catalog](https://www.heyvaldemar.com/services/) and find out how we can make your technological life better. Whether it's increasing the efficiency of your IT infrastructure, advancing your career, or expanding your technological horizons β€” I'm here to help you achieve your goals. From DevOps transformations to building gaming computers β€” let's make your technology unparalleled! + +## Patreon Exclusives + +πŸ† Join my [Patreon](https://www.patreon.com/heyvaldemar) and dive deep into the world of Docker and DevOps with exclusive content tailored for IT enthusiasts and professionals. As your experienced guide, I offer a range of membership tiers designed to suit everyone from newbies to IT experts. + +## My Recommendations + +πŸ“• Check out my collection of [essential DevOps books](https://kit.co/heyvaldemar/essential-devops-books)\ +πŸ–₯️ Check out my [studio streaming and recording kit](https://kit.co/heyvaldemar/my-studio-streaming-and-recording-kit)\ +πŸ“‘ Check out my [streaming starter kit](https://kit.co/heyvaldemar/streaming-starter-kit) + +## Follow Me + +🎬 [YouTube](https://www.youtube.com/channel/UCf85kQ0u1sYTTTyKVpxrlyQ?sub_confirmation=1)\ +🐦 [X / Twitter](https://twitter.com/heyvaldemar)\ +🎨 [Instagram](https://www.instagram.com/heyvaldemar/)\ +🐘 [Mastodon](https://mastodon.social/@heyvaldemar)\ +🧡 [Threads](https://www.threads.net/@heyvaldemar)\ +🎸 [Facebook](https://www.facebook.com/heyvaldemarFB/)\ +🧊 [Bluesky](https://bsky.app/profile/heyvaldemar.bsky.social)\ +πŸŽ₯ [TikTok](https://www.tiktok.com/@heyvaldemar)\ +πŸ’» [LinkedIn](https://www.linkedin.com/in/heyvaldemar/)\ +πŸ“£ [daily.dev Squad](https://app.daily.dev/squads/devopscompass)\ +🧩 [LeetCode](https://leetcode.com/u/heyvaldemar/)\ +🐈 [GitHub](https://github.com/heyvaldemar) + +## Community of IT Experts + +πŸ‘Ύ [Discord](https://discord.gg/AJQGCCBcqf) + +## Refill My Coffee Supplies + +πŸ’– [PayPal](https://www.paypal.com/paypalme/heyvaldemarCOM)\ +πŸ† [Patreon](https://www.patreon.com/heyvaldemar)\ +πŸ’Ž [GitHub](https://github.com/sponsors/heyvaldemar)\ +πŸ₯€ [BuyMeaCoffee](https://www.buymeacoffee.com/heyvaldemar)\ +πŸͺ [Ko-fi](https://ko-fi.com/heyvaldemar) + +🌟 **Bitcoin (BTC):** bc1q2fq0k2lvdythdrj4ep20metjwnjuf7wccpckxc\ +πŸ”Ή **Ethereum (ETH):** 0x76C936F9366Fad39769CA5285b0Af1d975adacB8\ +πŸͺ™ **Binance Coin (BNB):** bnb1xnn6gg63lr2dgufngfr0lkq39kz8qltjt2v2g6\ +πŸ’  **Litecoin (LTC):** LMGrhx8Jsx73h1pWY9FE8GB46nBytjvz8g + +
+ +### Show some πŸ’œ by starring some of the [repositories](https://github.com/heyValdemar?tab=repositories)! + +![octocat](https://user-images.githubusercontent.com/10498744/210113490-e2fad07f-4488-4da8-a656-b9abbdd8cb26.gif) + +
+ +![footer](https://user-images.githubusercontent.com/10498744/210157572-1fca0242-8af2-46a6-bfa3-666ffd40ebde.svg) diff --git a/ollama-traefik-letsencrypt-docker-compose.yml b/ollama-traefik-letsencrypt-docker-compose.yml index 43d2551..305d102 100644 --- a/ollama-traefik-letsencrypt-docker-compose.yml +++ b/ollama-traefik-letsencrypt-docker-compose.yml @@ -1,44 +1,3 @@ -# Ollama with Let's Encrypt Using Docker Compose - -# The complete installation guide is available on my website https://www.heyvaldemar.com/install-ollama-using-docker-compose/ - -# Change variables in the `.env` to meet your requirements. -# Note that the `.env` file should be in the same directory as `ollama-traefik-letsencrypt-docker-compose.yml`. - -# Create networks for your services before deploying the configuration using the commands: -# `docker network create traefik-network` -# `docker network create ollama-network` - -# Deploy Ollama using Docker Compose: -# `docker compose -f ollama-traefik-letsencrypt-docker-compose.yml -p ollama up -d` - -# Author -# I’m Vladimir Mikhalev, the Docker Captain, but my friends can call me Valdemar. -# https://www.docker.com/captains/vladimir-mikhalev/ - -# My website with detailed IT guides: https://www.heyvaldemar.com/ -# Follow me on YouTube: https://www.youtube.com/channel/UCf85kQ0u1sYTTTyKVpxrlyQ?sub_confirmation=1 -# Follow me on Twitter: https://twitter.com/heyValdemar -# Follow me on Instagram: https://www.instagram.com/heyvaldemar/ -# Follow me on Threads: https://www.threads.net/@heyvaldemar -# Follow me on Mastodon: https://mastodon.social/@heyvaldemar -# Follow me on Bluesky: https://bsky.app/profile/heyvaldemar.bsky.social -# Follow me on Facebook: https://www.facebook.com/heyValdemarFB/ -# Follow me on TikTok: https://www.tiktok.com/@heyvaldemar -# Follow me on LinkedIn: https://www.linkedin.com/in/heyvaldemar/ -# Follow me on GitHub: https://github.com/heyvaldemar - -# Communication -# Chat with IT pros on Discord: https://discord.gg/AJQGCCBcqf -# Reach me at ask@sre.gg - -# Give Thanks -# Support on GitHub: https://github.com/sponsors/heyValdemar -# Support on Patreon: https://www.patreon.com/heyValdemar -# Support on BuyMeaCoffee: https://www.buymeacoffee.com/heyValdemar -# Support on Ko-fi: https://ko-fi.com/heyValdemar -# Support on PayPal: https://www.paypal.com/paypalme/heyValdemarCOM - networks: traefik-network: external: true @@ -69,16 +28,27 @@ services: retries: 3 start_period: 90s labels: + # Enable Traefik for this container - "traefik.enable=true" + # Match incoming requests on a specific hostname - "traefik.http.routers.webui.rule=Host(`${OLLAMA_HOSTNAME}`)" + # Assign the router to a named Traefik service - "traefik.http.routers.webui.service=webui" + # Use the 'websecure' (HTTPS) entry point - "traefik.http.routers.webui.entrypoints=websecure" + # Define the internal container port for routing - "traefik.http.services.webui.loadbalancer.server.port=8080" + # Enable TLS on this router - "traefik.http.routers.webui.tls=true" + # Use Let's Encrypt for certificate management - "traefik.http.routers.webui.tls.certresolver=letsencrypt" + # Pass the original Host header to the container - "traefik.http.services.webui.loadbalancer.passhostheader=true" + # Apply a compression middleware - "traefik.http.routers.webui.middlewares=compresstraefik" + # Define settings for the compression middleware - "traefik.http.middlewares.compresstraefik.compress=true" + # Specify which Docker network Traefik should use for routing - "traefik.docker.network=traefik-network" restart: unless-stopped depends_on: @@ -113,11 +83,17 @@ services: retries: 3 start_period: 30s labels: + # Enable Traefik for this container - "traefik.enable=true" + # Define TCP router rules for Ollama to match all incoming requests (HostSNI) - "traefik.tcp.routers.ollama.rule=HostSNI(`*`)" + # Assign the Ollama router to a named Traefik service - "traefik.tcp.routers.ollama.service=ollama" + # Use the 'ollama' (custom) entry point - "traefik.tcp.routers.ollama.entrypoints=ollama" + # Define the internal container port for routing to the Ollama service - "traefik.tcp.services.ollama.loadbalancer.server.port=11434" + # Specify which Docker network Traefik should use for routing - "traefik.docker.network=traefik-network" restart: unless-stopped depends_on: @@ -127,34 +103,51 @@ services: traefik: image: ${TRAEFIK_IMAGE_TAG} command: + # Set the log level (DEBUG, INFO, WARN, ERROR) - "--log.level=${TRAEFIK_LOG_LEVEL}" - - "--accesslog=true" + # Enable the built-in API and web-based dashboard on /dashboard - "--api.dashboard=true" - - "--api.insecure=true" + # Enable the /ping endpoint so we can health-check Traefik - "--ping=true" + # Assign the /ping endpoint to a dedicated entry point on port 8082 - "--ping.entrypoint=ping" - - "--entryPoints.ping.address=:8082" - - "--entryPoints.web.address=:80" - - "--entryPoints.websecure.address=:443" + - "--entrypoints.ping.address=:8082" + # Define the primary HTTP entry point on port 80 + - "--entrypoints.web.address=:80" + # Define the secure (HTTPS) entry point on port 443 + - "--entrypoints.websecure.address=:443" + # Define the custom Ollama entry point on port 11434 - "--entryPoints.ollama.address=:11434" + # Enable the Docker provider to detect containers and their labels - "--providers.docker=true" + # Point Traefik to the Docker socket - "--providers.docker.endpoint=unix:///var/run/docker.sock" - - "--providers.docker.exposedByDefault=false" + # Prevent automatic exposure of all containers; only expose containers + # with "traefik.enable=true" + - "--providers.docker.exposedbydefault=false" + # Use ACME (Let's Encrypt) to generate/renew certificates via TLS challenge - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" + # The email address used by Let's Encrypt for renewal notices - "--certificatesresolvers.letsencrypt.acme.email=${TRAEFIK_ACME_EMAIL}" + # The file where ACME certificates are stored inside the container - "--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json" + # Enable Prometheus metrics - "--metrics.prometheus=true" + # Configure Prometheus histogram buckets - "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0" - - "--global.checkNewVersion=true" - - "--global.sendAnonymousUsage=false" + # Check for newer Traefik versions and optionally log that info + - "--global.checknewversion=true" + # Disable sending anonymous usage data to the Traefik maintainers + - "--global.sendanonymoususage=false" volumes: - - /var/run/docker.sock:/var/run/docker.sock + - /var/run/docker.sock:/var/run/docker.sock:ro - traefik-certificates:/etc/traefik/acme networks: - traefik-network ports: - "80:80" - "443:443" + - "11434:11434" healthcheck: test: ["CMD", "wget", "http://localhost:8082/ping","--spider"] interval: 10s @@ -162,16 +155,22 @@ services: retries: 3 start_period: 5s labels: + # Enable Traefik for this container. - "traefik.enable=true" + # A router to expose the Traefik dashboard - "traefik.http.routers.dashboard.rule=Host(`${TRAEFIK_HOSTNAME}`)" - - "traefik.http.routers.dashboard.service=api@internal" - "traefik.http.routers.dashboard.entrypoints=websecure" - - "traefik.http.services.dashboard.loadbalancer.server.port=8080" - "traefik.http.routers.dashboard.tls=true" - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt" - - "traefik.http.services.dashboard.loadbalancer.passhostheader=true" + - "traefik.http.routers.dashboard.service=api@internal" + # asic Authentication for the Traefik dashboard - "traefik.http.routers.dashboard.middlewares=authtraefik" - "traefik.http.middlewares.authtraefik.basicauth.users=${TRAEFIK_BASIC_AUTH}" + # Specify the internal server port to the dashboard service + - "traefik.http.services.dashboard.loadbalancer.server.port=8080" + # Pass the original Host header to the backend + - "traefik.http.services.dashboard.loadbalancer.passhostheader=true" + # HTTP -> HTTPS redirect for all hosts - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)" - "traefik.http.routers.http-catchall.entrypoints=web" - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"