Docker GenAI Stack on Windows using Docker Desktop
Tags: docker, llm, ai
Published: 2023-12-26 12:19:04

Approaching 2000 GitHub stars, [Docker GenAI Stack](https://github.com/docker/genai-stack) repository is gaining widespread traction, especially within the data science community. This stack is a collection of pre-configured Docker services designed to streamline the incorporation of large language models ([LLMs](https://collabnix.com/large-language-models-llms-and-docker-building-the-next-generation-web-application/)) and AI workflows into your development setup. It offers a user-friendly solution for handling and executing AI applications, eliminating the necessity for in-depth knowledge of LLMs or containerization.


![Image6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38jtyetd4s07bnsk3kvo.png)



In October 2023, at the Dockercon event, Docker unveiled the groundbreaking GenAI Stack for the very first time. This collaborative effort brought together the expertise of Docker, [Neo4j](https://collabnix.com/running-neo4j-in-a-docker-container-in-2-minutes/), LangChain, and Ollama. The primary objective behind this partnership was to forge a pre-configured GenAI stack comprising top-tier technologies. This stack not only boasts seamless integration but also includes sample applications, simplifying the onboarding process for developers and enabling them to dive into their projects effortlessly.

## What is GenAI Stack composed of?

This stack comprises a set of Docker containers designed to simplify the process of experimenting with the development and execution of Generative AI (GenAI) applications. Within these containers, a pre-built support agent application is available, catering to data import and response generation use-cases. The key components of the stack include:

## 1. Ollama
A management tool facilitating the handling of local Large Language Models (LLMs).

## 2. Neo4j
A database crucial for grounding. 

## 3. GenAI apps based on LangChain
Applications leveraging LangChain as the foundation for Generative AI functionalities.

## 4. Pre-configured LLMs
Jumpstart your AI projects with preconfigured Large Language Models such as Llama2, GPT-3.5, and GPT-4, embedded within the stack to enhance your development experience.

## Why Ollama, Neo4j and LangChain?

The collaboration with LangChain and Ollama stemmed from their specialized knowledge in Large Language Models (LLMs). LangChain serves as a programming and orchestration framework tailored for LLMs, while Ollama excels as a tool specifically designed for the local management and operation of LLMs.

Neo4j's involvement in the collaboration was driven by its proficiency in graph databases and knowledge graphs. Recognizing the potent synergy between graphs and LLMs, Neo4j identified the capability to construct highly accurate and reliable Generative AI (GenAI) applications through this amalgamation. The combined expertise of Ollama, Neo4j, and LangChain thus forms a robust foundation for the GenAI Stack, ensuring a comprehensive and effective solution for developers.

[Refer this link](https://collabnix.com/getting-started-with-genai-stack-powered-with-docker-langchain-neo4j-and-ollama/) if you're interested to setup Docker GenAI Stack on Mac or Linux system

## Getting Started

To kick off your journey with the GenAI Stack, follow these simple steps:

## Install Docker Desktop for Windows

Ensure you have Docker Desktop installed on your Windows machine. You can [download it from the official Docker website](https://docs.docker.com/desktop/install/windows-install/).

```
$ docker version
Client:
 Cloud integration: v1.0.35+desktop.5
 Version:           24.0.7
 API version:       1.43
 Go version:        go1.20.10
 Git commit:        afdd53b
 Built:             Thu Oct 26 09:08:44 2023
 OS/Arch:           windows/amd64
 Context:           default

Server: Docker Desktop 4.26.1 (131620)
 Engine:
  Version:          24.0.7
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.10
  Git commit:       311b9ff
  Built:            Thu Oct 26 09:08:02 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.25
  GitCommit:        d8f198a4ed8892c764191ef7b3b06d8a2eeb5c7f
 runc:
  Version:          1.1.10
  GitCommit:        v1.1.10-0-g18a0cb0
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

## Install Git

Git is a fundamental version control tool. If you don't have it installed, [grab it from the official Git website](https://git-scm.com/download/win) to empower collaborative development.

## Install WinGet

WinGet is a package manager for Windows that streamlines the installation of software packages. If you haven't installed WinGet yet, do so to enhance your system management capabilities.

With these essential tools in place, you're ready to dive into the world of Generative AI using the Docker GenAI Stack. Let the exploration begin!

## Configuration changes in Docker Desktop Settings

![Image5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3uiocet0drg8xh08ltl.png)


To optimize your Docker Desktop experience, follow these configuration changes:

- Navigate to Docker Desktop and select Settings.
- Under the General tab, locate the option:
*"Add the .docker.internal names to the host’s /etc/hosts file."
- Enable this option:
- Enabling this setting allows the resolution of *.docker.internal DNS names from both the host machine and your containers.

By incorporating this configuration change, you enhance the communication capabilities between your host and containers, fostering a smoother and more integrated Docker environment. Save the changes and elevate your Docker experience!


## Clone the repository


```
git clone https://github.com/docker/genai-stack
cd genai-stack
```


## Bringing up the Stack

```
docker compose up -d --build
```

Results:

```
 Container genai-stack-database-1  Creating
 Container genai-stack-pull-model-1  Creating
 Container genai-stack-pull-model-1  Created
 Container genai-stack-database-1  Created
 Container genai-stack-pdf_bot-1  Creating
 Container genai-stack-loader-1  Creating
 Container genai-stack-bot-1  Creating
 Container genai-stack-api-1  Creating
 Container genai-stack-pdf_bot-1  Created
 Container genai-stack-loader-1  Created
 Container genai-stack-api-1  Created
 Container genai-stack-front-end-1  Creating
 Container genai-stack-bot-1  Created
 Container genai-stack-front-end-1  Created
 Container genai-stack-pull-model-1  Starting
 Container genai-stack-database-1  Starting
 Container genai-stack-pull-model-1  Started
 Container genai-stack-database-1  Started
 Container genai-stack-database-1  Waiting
 Container genai-stack-pull-model-1  Waiting
 Container genai-stack-database-1  Waiting
 Container genai-stack-pull-model-1  Waiting
 Container genai-stack-database-1  Waiting
 Container genai-stack-pull-model-1  Waiting
 Container genai-stack-database-1  Waiting
 Container genai-stack-pull-model-1  Waiting
 Container genai-stack-pull-model-1  service "pull-model" didn't complete successfully: exit 1
 Container genai-stack-pull-model-1  service "pull-model" didn't complete successfully: exit 1
 Container genai-stack-pull-model-1  service "pull-model" didn't complete successfully: exit 1
 Container genai-stack-pull-model-1  service "pull-model" didn't complete successfully: exit 1
 Container genai-stack-database-1  Error
 Container genai-stack-database-1  Error
 Container genai-stack-database-1  Error
 Container genai-stack-database-1  Error
service "pull-model" didn't complete successfully: exit 1
```


The error message was expected. 
Reason - Ollama support for Windows is not yet available.
So, we might need to make changes and replace ollama with GPT-3.5 or GPT-4.0

Here’s the new Docker Compose file:


```
services:

  pull-model:
    image: genai-stack/pull-model:latest
    build:
      context: .
      dockerfile: pull_model.Dockerfile
    environment:
      - LLM=${LLM-gpt-3.5}
    networks:
      - net
    tty: true

  database:
    image: neo4j:5.11
    ports:
      - 7687:7687
      - 7474:7474
    volumes:
      - $PWD/data:/data
    environment:
      - NEO4J_AUTH=${NEO4J_USERNAME-neo4j}/${NEO4J_PASSWORD-password}
      - NEO4J_PLUGINS=["apoc"]
      - NEO4J_db_tx__log_rotation_retention__policy=false
    healthcheck:
        test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider localhost:7474 || exit 1"]
        interval: 5s
        timeout: 3s
        retries: 5
    networks:
      - net

  loader:
    build:
      context: .
      dockerfile: loader.Dockerfile
    volumes:
      - $PWD/embedding_model:/embedding_model
    environment:
      - NEO4J_URI=${NEO4J_URI-neo4j://database:7687}
      - NEO4J_PASSWORD=${NEO4J_PASSWORD-password}
      - NEO4J_USERNAME=${NEO4J_USERNAME-neo4j}
      - OPENAI_API_KEY=${OPENAI_API_KEY-}
      - EMBEDDING_MODEL=${EMBEDDING_MODEL-sentence_transformer}
      - LANGCHAIN_ENDPOINT=${LANGCHAIN_ENDPOINT-"https://api.smith.langchain.com"}
      - LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2-false}
      - LANGCHAIN_PROJECT=${LANGCHAIN_PROJECT}
      - LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY}
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
    networks:
      - net
    depends_on:
      database:
        condition: service_healthy
      pull-model:
        condition: service_completed_successfully
    x-develop:
      watch:
        - action: rebuild
          path: .
          ignore:
            - bot.py
            - pdf_bot.py
            - api.py
            - front-end/
    ports:
      - 8081:8080
      - 8502:8502


  bot:
    build:
      context: .
      dockerfile: bot.Dockerfile
    volumes:
      - $PWD/embedding_model:/embedding_model
    environment:
      - NEO4J_URI=${NEO4J_URI-neo4j://database:7687}
      - NEO4J_PASSWORD=${NEO4J_PASSWORD-password}
      - NEO4J_USERNAME=${NEO4J_USERNAME-neo4j}
      - OPENAI_API_KEY=${OPENAI_API_KEY-}
      - LLM=${LLM-gpt-3.5}
      - EMBEDDING_MODEL=${EMBEDDING_MODEL-sentence_transformer}
      - LANGCHAIN_ENDPOINT=${LANGCHAIN_ENDPOINT-"https://api.smith.langchain.com"}
      - LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2-false}
      - LANGCHAIN_PROJECT=${LANGCHAIN_PROJECT}
      - LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY}
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
    networks:
      - net
    depends_on:
      database:
        condition: service_healthy
      pull-model:
        condition: service_completed_successfully
    x-develop:
      watch:
        - action: rebuild
          path: .
          ignore:
            - loader.py
            - pdf_bot.py
            - api.py
            - front-end/
    ports:
      - 8501:8501

  pdf_bot:
    build:
      context: .
      dockerfile: pdf_bot.Dockerfile
    environment:
      - NEO4J_URI=${NEO4J_URI-neo4j://database:7687}
      - NEO4J_PASSWORD=${NEO4J_PASSWORD-password}
      - NEO4J_USERNAME=${NEO4J_USERNAME-neo4j}
      - OPENAI_API_KEY=${OPENAI_API_KEY-}
      - LLM=${LLM-gpt-3.5}
      - EMBEDDING_MODEL=${EMBEDDING_MODEL-sentence_transformer}
      - LANGCHAIN_ENDPOINT=${LANGCHAIN_ENDPOINT-"https://api.smith.langchain.com"}
      - LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2-false}
      - LANGCHAIN_PROJECT=${LANGCHAIN_PROJECT}
      - LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY}
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
    networks:
      - net
    depends_on:
      database:
        condition: service_healthy
      pull-model:
        condition: service_completed_successfully
    x-develop:
      watch:
        - action: rebuild
          path: .
          ignore:
            - loader.py
            - bot.py
            - api.py
            - front-end/
    ports:
      - 8503:8503

  api:
    build:
      context: .
      dockerfile: api.Dockerfile
    volumes:
      - $PWD/embedding_model:/embedding_model
    environment:
      - NEO4J_URI=${NEO4J_URI-neo4j://database:7687}
      - NEO4J_PASSWORD=${NEO4J_PASSWORD-password}
      - NEO4J_USERNAME=${NEO4J_USERNAME-neo4j}
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - LLM=${LLM-gpt-3.5}
      - EMBEDDING_MODEL=${EMBEDDING_MODEL-sentence_transformer}
      - LANGCHAIN_ENDPOINT=${LANGCHAIN_ENDPOINT-"https://api.smith.langchain.com"}
      - LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2-false}
      - LANGCHAIN_PROJECT=${LANGCHAIN_PROJECT}
      - LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY}
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
    networks:
      - net
    depends_on:
      database:
        condition: service_healthy
      pull-model:
        condition: service_completed_successfully
    x-develop:
      watch:
        - action: rebuild
          path: .
          ignore:
            - loader.py
            - bot.py
            - pdf_bot.py
            - front-end/
    ports:
      - 8504:8504
    healthcheck:
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 http://localhost:8504/ || exit 1"]
      interval: 5s
      timeout: 3s
      retries: 5

  front-end:
    build:
      context: .
      dockerfile: front-end.Dockerfile
    x-develop:
      watch:
        - action: sync
          path: ./front-end
          target: /app
          ignore:
            - ./front-end/node_modules/
        - action: rebuild
          path: ./front-end/package.json
    depends_on:
      api:
        condition: service_healthy
    networks:
      - net
    ports:
      - 8505:8505

networks:
  net:
```

## Re-building the GenAI Stack


```
docker compose up -d --build
```

## Verify the container services


![Image2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q3tntlbjy46l44yt7ue2.png)




```
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
genai-stack-api-1 genai-stack-api "uvicorn api:app --h…" api About an hour ago Up About an hour (healthy) 0.0.0.0:8504->8504/tcp
genai-stack-bot-1 genai-stack-bot "streamlit run bot.p…" bot About an hour ago Up About an hour (healthy) 0.0.0.0:8501->8501/tcp
genai-stack-database-1 neo4j:5.11 "tini -g -- /startup…" database About an hour ago Up About an hour (healthy) 0.0.0.0:7474->7474/tcp, 7473/tcp, 0.0.0.0:7687->7687/tcp
genai-stack-front-end-1 genai-stack-front-end "npm run dev" front-end About an hour ago Up About an hour 0.0.0.0:8505->8505/tcp
genai-stack-loader-1 genai-stack-loader "streamlit run loade…" loader About an hour ago Up About an hour (unhealthy) 0.0.0.0:8502->8502/tcp, 0.0.0.0:8081->8080/tcp
genai-stack-pdf_bot-1 genai-stack-pdf_bot "streamlit run pdf_b…" pdf_bot About an hour ago Up About an hour (healthy) 0.0.0.0:8503->8503/tcp
```

## Chat with your PDF File


![Image4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lbhig5nstw1xevl2f1v3.png)

## Resources

- [Running Neo4j in a Docker Container](https://collabnix.com/running-neo4j-in-a-docker-container-in-2-minutes/)
- [Large Language Models (LLMs) and Docker: Building the Next Generation Web Application](https://collabnix.com/large-language-models-llms-and-docker-building-the-next-generation-web-application/)
- [How to Containerise a Large Language Model(LLM) App with Serge and Docker](https://dev.to/ajeetraina/how-to-containerise-a-large-language-modelllm-app-with-serge-and-docker-2pif)
- [Understanding LLM Hallucination: Implications and Solutions for Large Language Models](https://collabnix.com/what-is-llm-hallucinations/)