각 프로그래밍 언어마다 빌드하는 과정이 다르고 특성도 다르다.
이러한 각 언어의 빌드와 특성을 이해해야지만 개발자가 만든 코드가 git에 올라오면 코드를 빌드하고 Docker image로 만들고 쿠버네티스에 올리는(=배포) 작업을 할 수 있는 것이다.
git에 올라온 코드에 대해서 빌드하고 image로 만들고 K8S에 올리는 배포과정 까지를 Automation하는 것을 CI/CD or pipelineing이라고 한다.
AWS에서 ubuntu이미지 20.04버전, t3.medium , 스토리지 40G, 인터넷에서 HTTP트래픽 허용 클릭한 보안그룹 생성, 키페어 생성 한 인스턴스 생성
ssh -i mykey.pem ubuntu@54.180.97.180
git clone https://github.com/c1t1d0s7/example-hello.git
sudo hostnamectl set-hostname mybuild
exec bash
#보기편하게 hostname 변경
sudo apt update
sudo apt install gcc -y
# gcc다운로드, ubuntu이기 때문에 apt로 설치
gcc hello.c -o hello # hello.c에 대해 hello실행파일 생성
file hello.c
file hello
./hello # 실행파일 hello의 내용이 출력
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) 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
sudo usermod -aG docker $USER # 일일이 sudo 안쓰고 관리자 권한으로 실행
docker image pull ubuntu:focal
vi Dockerfile
FROM ubuntu:focal # 이미지 다운
COPY hello /usr/local/bin/ # hello실행파일을 디렉터리에 복사
CMD ["/usr/local/bin/hello"] # 해당 디렉터리에서 복사된 hello실행파일 실행
docker image build -t hello-c .
scratch : 비어있는 이미지
vi Dockerfile
FROM scratch # 비어있는 이미지 사용
COPY hello /usr/local/bin/
CMD ["/usr/local/bin/hello"]
docker image build -t hello-c:scratch .
docker container run hello-c:scratch
- 예를들어 웹과 메신저가 있다고 가정하자. 각각은 TCP/IP통신을 해야한다. 각각 TCP/IP통신을 하기위한 라이브러리를 독자적으로 가지고 있는 것이 Static link 이다. 하지만 각각 라이브러리를 가지고 있다면 용량이 계속해서 늘어날 것이고 매우 비효율적이다.
- 따라서 이 경우에는 dynamic link 를 통해 TCP/IP 라이브러리를 외부에 놓고 메신저와 웹이 해당 라이브러리를 참조만 하는 형태로 구성한다.
- 하지만 Docker image생성에서는 현재 Static link를 사용하는 추세이다. 이유는, 필요한 라이브러리만 사용할 수 있기 때문에 오히려 이미지 측면에서는 용량을 줄일 수 있다.
📒 하지만 아직까지 대부분은 Dynamic link를 한다.
gcc hello.c -o hello # dynamic link
gcc hello.c -o hello-static --static # static link
vi Docekrfile
FROM scratch # scratch 이미지 사용
COPY hello-static /hello-static # static 실행파일 사용
CMD ["/hello-static"] # static 실행파일 실행
docker image build -t hello-c:static . # 이미지 생성
docker container run hello-c:static # run
#Build a binary with dynamically linked
FROM gcc:12 AS cbuilder
COPY . /usr/src/hello/
WORKDIR /usr/src/hello
RUN gcc hello.c -o hello
FROM ubuntu:focal
COPY --from=cbuilder /usr/src/hello/hello /hello
CMD ["/hello"]
wget https://go.dev/dl/go1.18.10.linux-amd64.tar.gz
tar xf go1.18.10.linux-amd64.tar.gz
sudo cp -r go /usr/local
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
source ~/.bashrc
go run hello.go # go파일 실행
go build -o hello . # go파일 실행파일로 빌드
./hello # 실행파일 실행
vi Dockerfile
FROM scratch
COPY hello /hello
CMD ["/hello"]
docker image build -t hello-go:scratch .
docker container run hello-go:scratch
FROM golang:1.18 AS gobuilder
ENV CGO_ENABLED=0
COPY . /usr/src/hello/
WORKDIR /usr/src/hello
RUN go build -o hello-http .
FROM scratch
COPY --from=gobuilder /usr/src/hello/hello-http /hello-http
CMD ["/hello-http"]
EXPOSE 3000/tcp
📌 빌드 순서
- 개발자가 개발을 하고 나온 코드를 add와 commit 그리고 push를 통해 remote repo에 올린다.
- 그 코드를 pull을 통해 갖고와서 언어에 맞게 run시켜보고 build를 통해 실행파일 형태로 생성한다.
- dockerfile을 열어 생성한 실행파일을 이용해 multi-build형태로 작성하던, static link / dynamic link를 사용하든 작성하고 , dockerfile을 build해서 이미지를 생성한다.
- 해당 이미지를 run시켜서 실행이 잘되는지 테스트하고 최종적으로 docker-hub와 같은 repository에 올린다
- k8s를 이용해 올라온 이미지를 이용해 배포하면 된다.
sudo apt install npm -y # nodejs실행시키는 컴파일러 설치
npm insatll # node_modules 생성
sudo apt install tree -y
tree # node_modules가 가진 디렉터리 계층 보기
npm start # .js파일을 실행시킨다
docker image pull node:16 # 이미지 다운
vi Dockerfile
FROM node:16
COPY . /usr/src/hello/
WORKDIR /usr/src/hello
RUN npm install
CMD ["npm", "start"]
EXPOSE 8080/tcp
docker image build -t hello-node . # 이미지 빌드
docker container run -d -p 8080:8080 hello-node
python에서 가상환경은 중요하다.
sudo apt install python3-pip
python3 -m pip install --user -U virtualenv
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc
source ~/.bashrc
virtualenv venv # 가상환경 이름
# 기존의 패키지와 분리된 별도의 가상환경을 생성
# 패키지가 격리된 환경에서 사용된다
source venv/bin/activate
# venv가상환경에 접속
pip install -r requirements.txt
# 시스템 전체에 설치하는 것이 아니라 가상환경에만 설치
deactivate
# 가상환경 나가기
export FLASK_APP=hello
flask run --host=0.0.0.0 --port=5000
# flask app실행
< 이미지 생성 및 실행 >
vi Dockerfile
FROM python:3.8
ENV FLASK_APP=hello
COPY . /usr/src/hello/
WORKDIR /usr/src/hello
RUN pip3 install -r requirements.txt
CMD ["flask", "run", "--host=0.0.0.0", "--port=5000"]
EXPOSE 5000/tcp
docker build -t hello-flask:v1 . # 이미지 생성
docker container run -d -p 5000:5000 hello-flask:v1
# detach모드, 포트포워딩해서 run
# 가상환경 deactivate한 후
virtualenv venv # 현재 디렉터리에 새로운 가상환경 생성
source venv/bin/activate # 가상환경 접속
pip install -r requirements.txt # 패키지 설치
python hello/manage.py runserver 0.0.0.0:8000
# django app 실행
< 이미지 생성 및 실행 >
vi Dockerfile
FROM python:3.8
COPY . /usr/src/hello/
WORKDIR /usr/src/hello
RUN pip3 install -r requirements.txt
CMD ["python3", "hello/manage.py", "runserver", "0.0.0.0:8000"]
EXPOSE 8000/tcp
docker build -t hello:v1 . # 이미지 생성
docker container run -d -p 8000:8000 hello:v1
# detach모드, 포트포워딩해서 run
< build lifecycle >
sudo apt install maven
lifecycle에서 중요한 4가지
clean
compile
test
package = complie + test
1 . jar파일
mvn package # target 생성
java -jar target/spring-hello-0.0.1.jar
# java파일 실행시키는 법
vi Dockerfile # 이미지 생성하기
FROM maven:3-openjdk-8 AS mbuilder
COPY . /usr/src/hello/
WORKDIR /usr/src/hello
RUN mvn package
FROM openjdk:8-jre
COPY --from=mbuilder /usr/src/hello/target/spring-hello-0.0.1.jar /usr/src/
CMD ["java", "-jar", "/usr/src/spring-hello-0.0.1.jar"]
# dockerfile 생성
docker image build -t hello-java . # 이미지 생성
docker container run hello-java # run
mvn clean # 새로운 빌드를 하기위해 기존의 package삭제
2 . war파일
war파일은 java기반의 web-application서버가 필요하다
mvn package # target 생성
sudo apt install tomcat9 -y
sudo cp hello-world.war /var/lib/tomcat9/webapps/
vi Dockerfile # 이미지 생성
FROM maven:3-openjdk-8 AS mbuilder
COPY . /usr/src/hello/
WORKDIR /usr/src/hello
RUN mvn package
FROM tomcat:8-jre8
COPY --from=mbuilder /usr/src/hello/webapp/target/webapp.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080/tcp
docker image build -t hello:war .
docker container run -d -p 8080:8080 hello:war
# image 생성 및 run