본문 바로가기

카테고리 없음

Docker

 

 

특정 버전의 이미지를 설치할 경우 :버전정보를 적으면 된다.

적지 않을 경우에는 가장 최신 버전으로 설치됨.

여기서 80:80의 의미는 "외부포트":"내부포트"를 의미한다.

우리가 주소창에 입력할 포트는 왼쪽(80일 경우 http)

 

 

docker build -t order_backend:v1.0 -f 도커파일위치 빌드컨텍스트위치(도커파일 입장에서 실행해야 될 경로)

 

도커파일을 프로젝트 루트 경로에 위치해놓고, cd로 도커 파일이 있는 곳까지 이동해서 실행해라

docker build -t order_backend:v1.0 -f ./Dockerfile . => ./Dockerfile 생략 가능 => docker build -t order_backend:v1.0 .

 

 

docker로 수정한 거 반영하기

1. docker build -t 옵션을 통해 order_system 이미지 생성 : 개인 차원에서 docker hub에 private/public 이미지 업로드 가능

2. docker run -d -p 옵션 실행

3. 수정

4. docker stop : 중지, docker rm : 컨테이너 삭제

5. docker build 다시 빌드

6. docker run

 

 

🖥️ Ordering 프로젝트로 알아보는 포트 호출 구조

back end

localhost 3306 찾으러 내부로 가는데 3306 포트를 사용하지 않아 에러

backend에서는 localhost가 자기 자신(back end)이기 때문이다.

자기 자신에서 3306포트에 mariadb가 있는 게 아니라, 다른 곳이기 때문에 우리가 원하는대로 접근하지 못한다.

-> 해결 방법 2가지

 

 

front end

localhost 8080 찾으러 내부로 감. 

front는 host에다가 화면을 주고, host 입장에서 외부포트로 적혀있는 8080을 찾아서 back end로 가서 문제가 생기지 않음.

 

 

🖥️ nginx config 파로 알아보는 포트 호출 구조

localhost:8080/item-service/~로 들어오면 8081과 8082로 분배

 

 

🖥️ 도커로 주요 서비스 실행

 

<SQL>

설치 : docker run --name board_mysql -e MYSQL_ROOT_PASSWORD=1234 -d -p 3306:3306 mysql:latest

 

<REDIS>

설치 : docker run -p 6379:6379 redis

설치 시 이름지정 : docker run --name myredis -d -p 6379:6379 redis

실행 : docker exec -it /bin/sh -> redis cli

바로 실행 : docker exec -it myredis redis-cli

 

 

 

 

🖥️ Docker로 java 간단하게 실행하기 - Dockerfile 스크립트 작성하기

 

 

Dockerfile이 있는 곳으로 이동 -> docker build -t myjava:v1.0 . 실행 -> docker images로 java파일 확인 후 실행

 

 

# 컨테이너 내에서 사용할 java 설치
FROM openjdk:11

# 작업 디렉토리 설정. docker 컨테이너 내부 폴더 설정
WORKDIR /app

# 로컬 호스트의 HelloWorld.java 파일을 컨테이너의 /app 폴더로 복사
COPY HelloWorld.java /app

RUN javac HelloWorld.java

# 실행 작업
CMD ["java", "HelloWorld"]

 

docker build -t myjava:v2.0 . -> docker images

 

 

🖥️ Docker compose - 2개의 컨테이너를 동시에 실행해보자

 

 

 

docker-compose.yml

# docker-compose 파일 format에 대한 버전
version: "3.8"
services:
  java-app1:
    build:
      context: .
      dockerfile: DockerfileJava1
    image: myjava1:v1

  java-app2:
    build:
      context: .
      dockerfile: DockerfileJava2
    image: myjava2:v1

 

docker-compose가 있는 위치로 가서 수행해야 함 !!!

Hello world java1과 java2가 잘 출력됐다!!!!

 

(+) docker-compse up => 테스트해보니 문제 => docker-compose down => 수정 => 이미 이미지가 남아있어서 docker-compose up해도 있는 이미지 실행 => docker-compose build를 통해 이미지 업데이트 => docker-compose up

 

 

🖥️ Ordering 프로젝트에 적용

 

 

BackEnd

 

 

Dockerfile

FROM openjdk:11 as stage1

WORKDIR /app

# gradle 빌드 시에 필요한 파일들을 Docker의 workdir로 copy
COPY gradlew .
# 일반적으로 폴더 전체를 복사할 때는 폴더 이름을 같이 적어줌 : gradle 폴더를 gradle이라는 이름으로 COPY
COPY gradle gradle 
COPY build.gradle .
COPY settings.gradle .
COPY src src

# bootJar : plain jar만 얻음
# /app/build/libs/*.jar 파일 아래 명령어를 통해 생성
RUN ./gradlew bootJar

# 새로운 스테이지 시작
FROM openjdk:11

WORKDIR /app

COPY --from=stage1 /app/build/libs/*.jar app.jar

# CMD 또는 ENTRYPOINT를 통해 컨테이너 실행
# 프로젝트 때 버전관리 어떻게 할 것인가?
ENTRYPOINT ["java", "-jar", "app.jar"]

 

 

 

실행 명령어

 

1. docker build -t ordering:v1 .

2. docker run -d -p 8080:8080 ordering:v1

3. docker ps -a

4. docker logs CONTAINER_ID

 

Ordering에 mariaDB 붙이기 - 해결 방법 1

 

 

 

 

 

 

 

FrontEnd

 

 

Dockerfile

FROM node:20

WORKDIR /app

COPY . .

RUN npm install

ENTRYPOINT ["npm", "run", "serve"]

 

 

.dockerignore

node_modules
dist

 

 

실행 명령어

 

0. frontend 폴더로 이동

1. docker build -t ordering-frontend:v1 .

2. docker run -d -p 8081:8080 ordering-frontend:v1

3. docker ps -a

4. docker logs CONTAINER_ID

 

포트 지정이 어렵다...........!

외부는 무조건 8081. 내부에서는 8081로 띄우기 때문에 8081:8181이어야 하지만, 8081:8080도 상관없다.

=> localhost:8081 => 프론트 화면이 나온다. => 로그인 => 사용자 웹 브라우저에 보이는 도메인이 서버로 전달(8081)

docker run -d -p 8081:8080 ordering-frontend :v1

 

 

BackEnd, FrontEnd 모두 예쁘게 Docker에 올라갔다!!!!

 

 

 

 

package.json에 프론트의 내부 포트를 지정해주었기 때문에

docker run -d -p 8081:8081 ordering-frontend :v1으로 실행해준 거였다.

지정해주지 않으면 기본이 8080이기 때문에 docker run -d -p 8081:8080 ordering-frontend :v1로 입력해주면 된다.

 

 

 

이미지 저장하는 경로가 이전에는 C 드라이브 ~ 여서 도커 환경에서는 해당 이미지를 불러올 수가 없게 된다.

그래서 ItemService의 creat와 update 메서드의 이미지 저장 경로를 도커 백엔드의 폴더명(/tmp/)으로 변경해줬다.

 

 

 

완전히 다른 HOST로 접속해서 docker 백엔드 > tmp 폴더에 사진이 저장되고 있는지 확인 > 종료는 exit

/bin/bash 명령어로 들어가면 root@CONTAINER_ID 요런 형식으로 뜸 !

 

고유 id 값_이미지 이름 형식으로 잘 올라가 있다.

 

 

문제점

1. Docker Container가 삭제되면 이미지 파일도 삭제된다

-> 컨테이너는 빈번하게 삭제되고 업로드 되니 중요한 정보들을 잃어버리면 안된다.

-> 컨테이너 밖 host의 특정 공간과 연결해(volume) 데이터를 컨테이너 밖 host에 지정

 

 

Docker - v 옵션 : HOST 저장소 연결

 

HOST 폴더와 Docker를 volume(-v)를 통해 연결

 

 

컨테이너를 삭제하고 다시 실행해도 바탕화면의 tmp 폴더에 이미지가 저장되어 이미지 파일을 다시 불러올 수 있다.

 

특히 log를 host에 남길 때 자주 사용한다.

하지만 항상 아래 형식으로 실행시켜 줘야하니까 번거롭다 -> docker-compose에서 쉽게 할 수 있다.

docker run -d -p 8080:8080 -v C:/Users/Playdata/Desktop/tmp:/tmp ordering:v1

 

 

 

Docker - e 옵션 : 컨테이너에 환경 변수를 추가하는 옵션

 

-e SPRING_DATASOURCE_URL=jdbc:mariadb://host.docker.internal:3306/spring_order을 통해

도커를 실행할 때 application.yml에 url이  jdbc:mariadb://host.docker.internal:3306/spring_order로 대체된다.

 

 

💡 docker-compose 사용

 

docker run -d -p 8080:8080 -e SPRING_DATASOURCE_URL=jdbc:mariadb://host.docker.internal:3306/spring_order -v C:/Users/Playdata/Desktop/tmp:/tmp ordering:v1

 

위 명령어 기준으로 compose로 말아보자

 

docker-compose backend 연결

 

 

 

docker-compose를 down했다 up해도 이미지가 그대로 유지되어 있음 !!

 

 

 

Ordering에 mariaDB 붙이기 - 해결 방법 2

 

docker-compose frontend, db 연결

 

backend와 db를 연결할 때, host에 있는 db가 아니라, docker-compose에 같이 올리는 컨테이너 db인 mydb를 연결

docker-compose로 네트워크를 결합했기 때문에 mydb라는 서비스명으로  host 호출이 가능해지는 것이다.

 

backend에서 mydb를 사용하고 있지만, 생성 순서를 보장하지 않기 때문에 실행 시 에러가 발생한다.

따라서 depends_on 옵션 및 restart을 통해 mydb가 먼저 생성하도록 지정해주어야 한다.

 

docker-compose.yml

# docker-compose 파일 format에 대한 버전
version: "3.8"
services:
  mydb:
    image: mariadb
    environment:
      - MARIADB_ROOT_PASSWORD=1234
      # 스키마를 동시에 만들 수 있는 옵션
      - MARIADB_DATABASE=spring_order
  backend:
    build:
      # backend앱의 빌드 컨텍스트 위치 지정
      context: ./ordering
      dockerfile: Dockerfile
      # 실패하면 항상 재시작
    restart: on-failure
    ports:
      - "8080:8080"
    environment:
      # docker-compse에 네트워크를 결합했기 때문에 mydb라는 서비스명으로 host 호출 가능
      - SPRING_DATASOURCE_URL=jdbc:mariadb://mydb:3306/spring_order
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=1234
    volumes:
      # docker-compose의 특정경로의 image-path라는 이름으로 /tmp와 매핑
      - image-path:/tmp
      # # 직접 경로 매핑
      # - C:/Users/PlayData/Desktop/tmp:/tmp
    depends_on:
      # mydb가 먼저 생성된 이후에 backend를 생성하겠다라는 선언
      - mydb
  frontend:
    build:
      # backend앱의 빌드 컨텍스트 위치 지정
      context: ./ordering-frontend
      dockerfile: Dockerfile
    ports:
      - "8081:8081"
volumes:
  image-path:

 

 테스트

서비스 > MariaDB 중지

 

 

docker-compose up -d

docker ps -a

docker-compose down 

 

mydb가 먼저 생성된 채로 backend, frontend가 예쁘게 말려 올라간다.

 

테스트도 정상 작동 !!

 

 

 

 

 

 

 

 

이제 버전 2로 실습해보자.

 

git action을 통해 도커 이미지를 private push 해놓고, ec2에 SSH 접속해서 이미지를 다운로드해서 실행하는 방법이다.

ec2에서 docker 로그인 후에 pull하면 된다. 이때 docker run -e DB옵션을 준다.

 

만약에 docker-compose를 쓰고 싶다면, EC2에서 vi 작업으로 docker-compose 파일을 갖고 있게 하거나,

SCP를 넘겨주거나, ... 찾아보자.

 

 

1. docker hub에서 repository 생성

 

 

2. docker images에서 이전 backend 이미지를 모두 삭제해주고, backend폴더로 이동해서 docker 이미지 생성

 

docker 이미지 조회

 

 

3. docker desktop으로 로그인 후 cmd에서 도커 로그인

 

3-1

도커 데스크탑에서 로그인하는 것이 아닌, 터미널 창에서 도커 로그인

이때 로그인 안된다면 docker hub에서 비밀번호 변경할 것

 

 

 

4. dockerHub에 이미지 push

 

이미지 업로드 성공!

 

 

 

 

2024.03.05

1. 도커 데스크탑에서 로그인하는 것이 아닌, 터미널 창에서 도커 로그인

 

2. docker hub에 private repo 생성

 

3. private repo에 backend v1이미지 업로드

 

 

4. private repo에 backend v2이미지 업로드

Dockerfile에 권한 추가

]

 

Docker v2 스크립트 작성

git secrets에 DOCKER_USERNAME, DOCKER_PASSWORD 등록

 

 

add, commit, push 후 gitaction 실행

 

 

 

 

5. AWS 설정

EC2 프리티어 한대, RDS 프리티어 한대 만들고 스키마 생성 후  secrets에 등록

Devops 참고해서 야무지게 RDS 만들어주고~

 

https://rookie-programmer.tistory.com/237

 

 

 

RDS workbench 연결 후 

deploy_server_with_docker_ec2.yaml 에 있는 스키마 명과 동일하게 스키마 생성

 

 

6. git secret에 스크립트에서 사용하는 변수들 추가

 

${{ secrets.EC2_HOST1 }} -> ec2 pulic DNS

${{ secrets.EC2_USERNAME }} -> ubuntu

${{ secrets.DB_HOST }} -> RDS 엔드포인트

${{ secrets.DB_USERNAME }} -> admin

${{ secrets.DB_PASSWORD }} -> RDS 비밀번호

 

 

 

ec2 ssh로 터미널 접속

pem키가 있는 경로로 이동 -> ssh ~~~ 실행

 

방금 만든 이미지(컨테이너)가 가동 중인지 확인.

 

 

 

 

만약 ec2가 늘어나 scale-out을 고려해야 한다면?

서버가 늘어날 때마다 ec2를 생성하고, 스크립트에 넣어줘야 하는 번거로움이 생긴다.

-> 컨테이너가 들어가 있는 노드의 집합인 클러스터를 자동으로 관리하는 쿠버네티스를 사용하는 이유가 된다.