docker image build & run 활용

이동명·2023년 10월 12일
0
post-thumbnail

저번 docker 포스팅에서는 docker hub 에서 image 를 pull 받고 사용해봤다. 오늘은 Dockerfile 을 작성해보고 build 하고 container에서 실행까지 해보도록 하겠다.

Dockerfile 작성

일단 시작으로.. DockerFile 이라고 만들면 안 된다.. f 소문자로 하자..

mysql 을 build 와 run을 해보자..

FROM mysql:latest
VOLUME C:\tmp\mysql:/var/lib/mysql
ENV MYSQL_ROOT_PASSWORD=1234
EXPOSE 3306

docker build

위의 코드처럼 Dockerfile 을 작성해주고.. build를 해주자..

docker build . -t mysql

docker desktop image에 등록된 모습

docker run

build 한 imgae를 아래의 명령어로 실행시켜보자.

난 현재 local에 mysql 이 3306을 먹고 있었기 때문에 포트를 3307로 엮어주었음.

docker run --name mysql -p 3307:3306 -d mysql

로컬에서도 3307로 접근이 가능해졌다.

jar 실행 Dockerfile

DB는 컨테이너에 띄워놓았으니 demo project를 build해서 jar파일을 Dockerfile 과 같은 경로에 옮겨놓고 image를 build 해 보자.

jar 압축파일을 Dockerfile과 같은 경로에 있다고 가정하고 진행.

여기서 조금 중요한 건 datasource url 을 localhost 나 혹은 다른 외부 ip로 접근하면 mysql 에 접근할 수 없다는 것 이다.

이유는 db가 실행중인 container 쪽에 접근을 해야 커넥션이 되기 때문이다.

따라서 다음 명령어로 mysql container 쪽의 주소를 알기 위해 접근을 해봤다.

bridge 쪽으로 접근하면 이것저것 설정이 나오는데 그 중 Containers 설정을 보자..

docker network inspect bridge

mysql container 쪽 주소 같은데 datasource쪽 url 을 사진쪽으로 붙어야 접근이 가능해진다.

다 하고 나서 알게 되었지만 ip주소말고 Name 으로 접근해도 된다.

spring:
  datasource:
  	// url: jdbc:mysql://mysql:3306/test?serverTimezone=Asia/Seoul
    url: jdbc:mysql://172.17.0.2:3306/test?serverTimezone=Asia/Seoul
    username: root
    password: 1234
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true

# java 17 사용
FROM openjdk:17

# 현재경로에 있는 jar파일을 현재경로 app.jar로 copy
COPY ./*.jar /app.jar

# 확인용..
RUN ["java","--version"]

# jar 실행 명령어
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]

# 8001 port 로 빼줌..
EXPOSE 8001

build 하자

docker build -f ./Dockerfile-sptest -t sptest .

run 하자

docker run --name sptest -p 9000:8001 -d sptest

9000 포트에 엮었기 때문에 9000번 포트에서 돌아가고 있는 모습

docker repository - cloud 에서 작업

일단 cloud 에서 작업을 하기 위해 지난번에 만들어뒀던 GCP 에 인스턴스 하나를 생성하고 putty 로 접속 하였다.

일단.. sudo apt update 하자

그리고 docs를 보면서 진행해보자, 나는 데비안 배포판을 사용중이다.

docs 링크 : https://docs.docker.com/engine/install/debian/

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

위의 명령어를 차례대로 입력해서 일단 docker를 설치해주자..

설치가 완료 되었고, 앞으로 계속 sudo 권한을 사용해야 하기 때문에 귀찮으니까 사용자를 Docker 그룹에 추가하자.. 여기서 ${USER}는 현재 로그인한 사용자의 이름으로 대체된다.

sudo usermod -aG docker ${USER}

# reload
sudo systemctl  reload docker

# 계정 전환 ( root 한번 전환 했다가 다시 전환 )
sudo su  
sudo su test

sudo 를 붙히지 않아도 된다.

일단 도커 설치까지만 끝났고 mysql container 먼저 돌리자..


sudo docker run --name my-mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=1234 -d mysql

mysql container가 실행되고 있는 모습

docker repository 생성 및 key 발급

repository 를 만들었으면 인증키를 발급받자.

이해를 돕기 위한 스크린 샷이다. key를 잃어버리지 말고 저장해놓자.

jar 실행

일단 프로젝트를 받아오자.

git clone https://github.com/dongmyoungLee/linux_test_be.git
FROM openjdk:17
RUN ["mkdir", "project"]
COPY . /app/
WORKDIR /app
RUN ["chmod", "744", "./project/gradlew"]
RUN ["./gradlew","clean", "build", "--no-debug"]
COPY build/libs/*T.jar app.jar

# jar실행
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","app.jar"]

원래는 Dockerfile을 위의 코드 처럼 Dockerfile에서 build를 진행하고 jar를 돌리는 코드로 짯었는데 에러가 있어서 확인 중.. 일단 포스팅은 cloud 에서 build 를 하는걸로 임시로 테스트를 해보겠다.

Dockerfile

# java 17
FROM openjdk:17

# app.jar 로 복사
COPY build/libs/*T.jar app.jar

# jar실행
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","app.jar"]

아래의 명령어들을 실행 하였음.


# java 17 설치
sudo apt install openjdk-17-jdk

# mysql container 로 접근
docker exec -it dcba626b5e05 /bin/bash

# mysql 접속
mysql -u root -p

# test db 생성
create database test;

# mysql exit
exit

# /bin/bast exit
exit

# cd
cd ./git clone project

# build
sh ./gradlew clean build

# image build
docker build -f ./Dockerfile -t server .

# run
docker run --name spring-server -p 8080:8001 -d server
	

8080 포트로 server 가 돌아가고 있는 모습

추가 jar build 추가 image 실행 (에러 트러블슈팅)

-> 작성예정

docker repo push 하기

docker login

username : dongmyounglee

password : 아까 생성한 key

build 하고 push 하자

docker build -t dongmyounglee/spring-test2 .

docker push dongmyounglee/spring-test2

push 된 모습

window에서 방금 push 한 repo 사용

docker run -d -p 9001:8001 dongmyounglee/spring-test2

build 되고 run 된 모습

설정한 9001 포트로 server 가 돌아가고 있는 모습

위의 사진처럼 cloud 에서 설정해서 build 한 옵션들을 window에서도 그대로 사용이 가능하다. 좀 충격적이다.

프론트도 docker를 이용해서 배포 해보자

프론트 배포를 위해선 nginx 를 사용해서 내 외부 ip 에 접근했을 때 보여줄 index.html 을 내 프로젝트 빌드 산출물로 대체 해야한다.

따라서 내 생각에는 ..

Dockerfile

아래처럼 코드를 작성하고,

FROM nginx
COPY ./build/* /usr/share/nginx/html/
COPY ./default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

default.conf 를 작성해서 꽂으면 될 것 같았는데 ..

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /usr/share/nginx/html;

    index index.html index.htm;

    location / {
        try_files $uri /index.html;
    }

    access_log /var/log/nginx/front_acc.log;
    error_log /var/log/nginx/front_arr.err;
}

막상 실행해서 보니 페이지 헤더 까지는 적용이 되는 것 같은데 static 폴더의 파일을 불러오지 못하는 것 같다..

이 이슈는 추후에 조금 더 트러블 슈팅 해봐야 할 것 같아서,

일단 npm을 이용해야 할 것 같다.

Dockerfile

FROM node:18.18.1-slim
RUN ["mkdir", "app"]
COPY ./src ./app/src
COPY ./public ./app/public
COPY package.json ./app/package.json
COPY package-lock.json ./app/package-lock.json
WORKDIR ./app
RUN ["npm", "install"]
ENTRYPOINT ["npm", "start"]

clone 받자..

git clone https://github.com/dongmyoungLee/linux_test_fe.git

# build
docker build -f ./Dockerfile -t front .

# run
docker run --name front -p 80:3000 -d front

외부 ip 에서 npm 이 돌아가고 있는 모습

추가 nginx 방식 (에러 트러블슈팅)

-> 위쪽 에서 nginx 설정이 무언가 충돌이나고 포트도 충돌이 나서 nginx를 사용해서 배포하기가 쉽지 않았다..

충돌을 해결한 Dockerfile 을 다시 게시하겠음.

Dockerfile

FROM node:18.18.1-slim AS builder
RUN ["mkdir", "app"]
COPY ./src ./app/src
COPY ./public ./app/public
COPY package.json ./app/package.json
COPY package-lock.json ./app/package-lock.json
WORKDIR ./app

# 장비에서 build 는 docker 에 부담을 주기 때문에 조금 지양하는 편..
# local 에서 build 해주는게 낫긴 함..
RUN npm install
RUN npm run build

# 파일이 충돌이 나는 것 같음. port도 80이 충돌 나는것 같음.
FROM nginx
COPY ./default.conf /etc/nginx/conf.d/p.conf
COPY --from=builder /app/build /usr/share/nginx/app
EXPOSE 3000

default.conf

server {
    # port 80 충돌나니까 3000으로 하자..
    listen 3000;

    # 원본 건들지 말고 app에다 하자..
    root /usr/share/nginx/app;

    index index.html;

    location / {
        try_files $uri /index.html;
    }

    access_log /var/log/nginx/front_acc.log;
    error_log /var/log/nginx/front_arr.err;
}

이렇게 수정하고 배포에 성공했다!

추가 트러블슈팅

spring:
  datasource:
    url: jdbc:mysql://172.17.0.2:3306/test?serverTimezone=Asia/Seoul
    username: root
    password: 1234
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true

위쪽에서 포스팅 했던 부분인데 mysql container의 내부 ip로 접근했었는데 container name으로 접근을 해보겠다.

spring:
  datasource:
    url: jdbc:mysql://my-mysql:3306/test?serverTimezone=Asia/Seoul
    username: ${DB_USER}
    password: 1234
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true

일단 db 환경변수로 테이블 먼저 만들고 시작하자

docker run --name my-mysql -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=1234 -e MYSQL_DATABASE=test mysql

# sample network 생성
docker network create sample

# network list
docker network ls

# mysql container number
docker network connect sample 785145d9c1c2

# sample network 의 정보를 보면 ..
# containers 에 my-mysql 정보가 있을 것 이다.
docker network inspect sample

# netwokr 엮어서 실행하면 container name으로도 db connection 가능
docker run --name test --network sample test

profile
Web Developer

0개의 댓글