Skip to content

TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), Docker + GHCR 기반 Nginx 웹페이지 배포 실습, Nginx Dockerfile 이미지 GHCR에 Push & Render 배포] #71

Open

Description

@soheeGit

📌 바이브 코딩(Vibe Coding)

인공지능(AI)을 활용하여 자연어로 프로그램을 개발하는 새로운 방식
즉, 사용자가 원하는 기능을 일상적인 언어로 설명하면 AI가 이를 해석하여 실제로 동작하는 코드를 생성해주는 프로그래밍 패러다임

바이브 코딩의 장점

  • 접근성 향상: 비전문가도 개발에 참여할 수 있어 창업자, 디자이너 등 다양한 분야에서 활용 가능하다.
  • 생산성 증가: 반복적인 작업을 AI가 처리하여 개발 속도를 높인다.
  • 창의성 촉진: 기술적인 제약 없이 아이디어를 자유롭게 구현할 수 있다.

바이브 코딩의 한계

  • 정확성 문제: AI가 생성한 코드가 항상 정확하거나 최적화되어 있지 않을 수 있다.
  • 의존성 증가: AI에 과도하게 의존하면 개발자의 기본 실력이 저하될 우려가 있다.
  • 윤리적·법적 이슈: AI가 생성한 코드의 저작권 문제 등 법적 논란이 발생할 수 있다.

📌 Ollama

Llama 3, Mistral, Gemma 등 다양한 오픈소스 대형 언어 모델(LLM)을 로컬에서 실행할 수 있게 해주는 경량 프레임워크
개인 정보 보호, 비용 절감, 오프라인 환경에서의 AI 활용 등을 원하는 사용자에게 적합하다.
https://ollama.com/

Ollama 기본 사용법

  1. 모델 실행
    예를 들어, Llama 3 모델을 실행하려면 : ollama run llama3
    처음 실행 시 모델이 자동으로 다운로드된다.
  2. 모델 목록 확인
    로컬에 설치된 모델 목록을 확인하려면 : ollama list
  3. 모델 정보 확인
    특정 모델의 정보를 확인하려면 : ollama show [모델명]
  4. 모델 제거
    더 이상 사용하지 않는 모델을 제거하려면 : ollama rm [모델명]

주요 특징

  • 다양한 모델 지원: Llama 3, Mistral, Gemma 등 다양한 오픈소스 LLM을 지원한다.
  • 로컬 실행: 인터넷 연결 없이도 로컬에서 모델을 실행할 수 있다.
  • REST API 제공: 다른 애플리케이션과의 통합을 위한 REST API를 제공한다.
  • 모델 커스터마이징: 사용자 정의 프롬프트로 모델을 커스터마이징할 수 있다.

경량화 버전으로 실습해보기

Alpine Linux 기반으로 경량화된 Ollama Docker 이미지를 제공하는 비공식 프로젝트
https://github.com/alpine-docker/ollama

docker pull alpine/ollama
docker rm -f ollama
docker run -d -p 11434:11434 -v ~/.ollama/root/.ollama --name ollama alpine/ollama
docker exec -ti ollama ollama pull llama3.2

포스트맨에서 확인해보기

Image
{
    "error": "model requires more system memory (3.4 GiB) than is available (2.9 GiB)"
}

이렇게 뜬다면, Docker에 더 많은 메모리를 할당해야 한다.
본인은 rancher desktop을 사용하고 있어 preference -> Virtual Machine -> Memory (GB)를 6으로 늘려줬다.

Image

메모리 설정 변경 후 아래 명령어로 기존 컨테이너를 다시 시작한다.

docker rm -f ollama
docker run -d -p 11434:11434 -v ~/.ollama/root/.ollama --name ollama alpine/ollama
docker exec -ti ollama ollama pull llama3.2
Image Image Image

실습이 끝난 후에는 삭제하자!

docker ps # 실행중인 컨테이너 -> ID
docker rm -f {컨테이너 ID 앞 4자리}

📌 랭체인(LangChain)

LangChain = LLM + 체인(chain) 구조로 구성된 AI 파이프라인 프레임워크

주요 목적:

  • 단순한 질문-답변을 넘어서
  • 검색, 계산, 문서 요약, DB 질의, API 호출 등 다양한 작업을 조합
  • 이를 체인(chain) 으로 연결하여 복잡한 AI 앱을 구현

언어별 지원여부

언어 공식 지원 여부 설명
Python ✅ 지원 주력 플랫폼, 기능 가장 풍부
JavaScript / TypeScript ✅ 지원 웹/Node 기반 사용 가능
Java ❌ 미지원 직접 구현하거나 외부 연동 필요

LangChain4j 사용 (비공식 Java 프로젝트)

LangChain4j는 LangChain의 아이디어를 Java로 옮긴 비공식 프로젝트이다.

  1. 설치
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j</artifactId>
    <version>0.25.0</version> <!-- 최신 버전 확인 필요 -->
</dependency>
implementation 'dev.langchain4j:langchain4j:0.25.0'
  1. 기본 예제 (OpenAI API 호출)
import dev.langchain4j.model.openai.OpenAiChatModel;

public class Example {
    public static void main(String[] args) {
        OpenAiChatModel model = OpenAiChatModel.builder()
            .apiKey("YOUR_OPENAI_API_KEY")
            .build();

        String answer = model.generate("파이썬과 자바의 차이점은?");
        System.out.println(answer);
    }
}

3. 프롬프트 템플릿 사용
```java
import dev.langchain4j.*;

PromptTemplate template = PromptTemplate.from("Translate this to English: {{input}}");

String prompt = template.apply("안녕하세요");
System.out.println(prompt);
  1. 메모리 대화 (챗봇 스타일)
import dev.langchain4j.*;
import dev.langchain4j.memory.*;

public class ChatBot {
    public static void main(String[] args) {
        ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);

        OpenAiChatModel model = OpenAiChatModel.builder()
            .apiKey("YOUR_KEY")
            .build();

        ChatLanguageModel chat = model.withMemory(memory);

        System.out.println(chat.generate("안녕"));
        System.out.println(chat.generate("내가 방금 뭐라고 했지?"));
    }
}
  1. 문서 기반 질의응답 (RAG)
import dev.langchain4j.retriever.*;
import dev.langchain4j.store.embedding.inmemory.*;
import dev.langchain4j.model.embedding.openai.*;

public class RagExample {
    public static void main(String[] args) {
        InMemoryEmbeddingStore<Document> store = new InMemoryEmbeddingStore<>();

        OpenAiEmbeddingModel embedModel = OpenAiEmbeddingModel.builder()
            .apiKey("YOUR_KEY")
            .build();

        store.add(Document.from("서울은 대한민국의 수도입니다."));

        EmbeddingRetriever retriever = new EmbeddingRetriever(embedModel, store);
        retriever.retrieve("대한민국 수도는?").forEach(System.out::println);
    }
}

📌 Docker + GHCR 기반 Nginx 웹페이지 배포 실습

1단계. GitHub Token 발급 및 Docker 로그인

목적: GHCR(GitHub Container Registry)에 push할 수 있는 권한 부여

  1. GitHub에서 토큰 생성
Image Image
# 환경변수 등록
export GITHUB_TOKEN=ghp_abc123456

# 토큰 정상 확인
echo $GITHUB_TOKEN

# Docker 로그인
echo $GITHUB_TOKEN | docker login ghcr.io -u soheegit --password-stdin
  • GHCR은 반드시 소문자 사용자명만 허용한다 (soheegit ← OK)

2단계. Docker 이미지 pull → 태그 → GHCR에 push

목적: 공식 nginx 이미지를 GHCR에 내 소유 이미지로 업로드

docker pull nginx
docker tag nginx ghcr.io/soheegit/nginx:latest
docker push ghcr.io/soheegit/nginx
Image
  • GitHub > Packages에서 nginx 패키지가 생성된 것을 확인할 수 있음

3단계. GHCR에서 다시 pull 받아 웹서버 실행

목적: GHCR에 있는 이미지를 실제 서비스처럼 pull → run

docker rmi ghcr.io/soheegit/nginx:latest  # 캐시 제거 (선택)
docker pull ghcr.io/soheegit/nginx:latest
docker run -d -p 9999:80 --name my-nginx ghcr.io/soheegit/nginx:latest
Image

4단계. 컨테이너 내부에 직접 HTML 파일 삽입 (임시 방식)

docker exec -it my-nginx /bin/bash
echo Hello GHCR! > /usr/share/nginx/html/index.html
exit
  • 정적 파일을 직접 넣었을 때 웹서버에서 보여지는 방식 실습
Image

5단계. Volume 마운트를 사용한 웹 페이지 연결 (정식 방식)

목적: 로컬 폴더에 있는 HTML 파일을 컨테이너에 연동

mkdir -p ~/Development/workspace/docker/nginx
# 여기에 index.html 넣기 (예: VS Code에서 생성)

docker run -d -p 9988:80 -v  ~/Development/workspace/docker/nginx:/usr/share/nginx/html --name my-nginx-volume ghcr.io/soheegit/nginx:latest

6단계. 외부 접속용 localtunnel 실행

npm install -g localtunnel
lt --port 9988
Image Image

7단계. 로그 확인 (누가 접속했는지 확인)

docker logs my-nginx-volume
  • 내 사이트에 들어온 사람들의 로그를 볼 수 있다.

📌 Nginx Dockerfile 이미지 GHCR에 Push & Render 배포

  • 커스텀 index.html을 포함한 Nginx 이미지를 Dockerfile로 만들고
  • GHCR(GitHub Container Registry)에 업로드한 뒤
  • Render에서 pull하여 배포하는 전체 과정 실습

1. Dockerfile 작성

# base 이미지: nginx
FROM nginx

# index.html을 Nginx 기본 경로로 복사
COPY ./nginx/index.html /usr/share/nginx/html/index.html

# 포트 노출
EXPOSE 80

# nginx 실행
CMD ["nginx", "-g", "daemon off;"]
  • ./nginx/index.html 은 프로젝트 로컬 경로 기준
  • Nginx 기본 웹 경로는 /usr/share/nginx/html/

2. Docker 이미지 빌드 및 테스트 실행

docker build -t my-nginx .
docker run -d -p 8899:80 --name my-nginx-dockerfile my-nginx

3. GHCR에 Push

docker tag my-nginx ghcr.io/soheegit/my-nginx:latest
docker push ghcr.io/soheegit/my-nginx:latest
  • ghcr.io/USERNAME/REPO_NAME:TAG 형식
  • GHCR 로그인은 docker login ghcr.io 후 진행

4. 공개 이미지로 테스트 실행

docker run -d -p 8989:80 --name public-nginx-dockerfile ghcr.io/soheegit/my-nginx:latest
  • 외부에서도 GHCR에서 pull 가능 여부 테스트

5. 플랫폼 호환 이미지 (Render 용)

Render는 linux/amd64 기반이므로 플랫폼 명시하여 빌드:

docker build --platform linux/amd64 -t my-nginx:amd64 .
docker tag my-nginx:amd64 ghcr.io/soheegit/my-nginx:amd64
docker push ghcr.io/soheegit/my-nginx:amd64

6. Render 배포

  • Render → New Web Service 선택
  • Deploy from Docker Image 선택
  • Image URL:
ghcr.io/soheegit/my-nginx:amd64
  • Port: 80
  • 서비스 타입: Web Service (Public)
Image

Activity

  1. changed the title [-]TIL -2025-05-20 [바이브 코딩, Ollama][/-] [+]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain)][/+] on May 20, 2025
  2. changed the title [-]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain)][/-] [+]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), GHCR 실습][/+] on May 20, 2025
  3. changed the title [-]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), GHCR 실습][/-] [+]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), docker nginx 실습][/+] on May 20, 2025
  4. changed the title [-]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), docker nginx 실습][/-] [+]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), Docker + GHCR 기반 Nginx 웹페이지 배포 실습][/+] on May 20, 2025
  5. changed the title [-]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), Docker + GHCR 기반 Nginx 웹페이지 배포 실습][/-] [+]TIL -2025-05-20 [바이브 코딩, Ollama, 랭체인(LangChain), Docker + GHCR 기반 Nginx 웹페이지 배포 실습, Nginx Dockerfile 이미지 GHCR에 Push & Render 배포][/+] on May 20, 2025
  6. s0ooo0k commented on May 22, 2025

    @s0ooo0k

    💯 정리를 정말 잘하시네요 !!! 수업 중에 놓친 부분이 있었는데 ㅎㅎ 덕분에 참고하겠습니다 ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions