저번 docker 포스팅에서는 docker hub 에서 image 를 pull 받고 사용해봤다. 오늘은 Dockerfile 을 작성해보고 build 하고 container에서 실행까지 해보도록 하겠다.
일단 시작으로.. DockerFile 이라고 만들면 안 된다.. f 소문자로 하자..
mysql 을 build 와 run을 해보자..
FROM mysql:latest
VOLUME C:\tmp\mysql:/var/lib/mysql
ENV MYSQL_ROOT_PASSWORD=1234
EXPOSE 3306
위의 코드처럼 Dockerfile 을 작성해주고.. build를 해주자..
docker build . -t mysql
docker desktop image에 등록된 모습
build 한 imgae를 아래의 명령어로 실행시켜보자.
난 현재 local에 mysql 이 3306을 먹고 있었기 때문에 포트를 3307로 엮어주었음.
docker run --name mysql -p 3307:3306 -d mysql
로컬에서도 3307로 접근이 가능해졌다.
DB는 컨테이너에 띄워놓았으니 demo project를 build해서 jar파일을 Dockerfile 과 같은 경로에 옮겨놓고 image를 build 해 보자.
여기서 조금 중요한 건 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번 포트에서 돌아가고 있는 모습
일단 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가 실행되고 있는 모습
repository 를 만들었으면 인증키를 발급받자.
이해를 돕기 위한 스크린 샷이다. key를 잃어버리지 말고 저장해놓자.
일단 프로젝트를 받아오자.
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 가 돌아가고 있는 모습
-> 작성예정
docker login
username : dongmyounglee
password : 아까 생성한 key
build 하고 push 하자
docker build -t dongmyounglee/spring-test2 .
docker push dongmyounglee/spring-test2
push 된 모습
docker run -d -p 9001:8001 dongmyounglee/spring-test2
build 되고 run 된 모습
설정한 9001 포트로 server 가 돌아가고 있는 모습
위의 사진처럼 cloud 에서 설정해서 build 한 옵션들을 window에서도 그대로 사용이 가능하다. 좀 충격적이다.
프론트 배포를 위해선 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를 사용해서 배포하기가 쉽지 않았다..
충돌을 해결한 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