본문 바로가기
Study/Cloud,Docker,Kubernetes

Docker(3)-Dockerfile

by 왕방개 2024. 4. 4.

DockerFile

1.개요

=>DockerImage 을 생성하기 위한 스크립트

=>이미지를 사용하는 방법은 기존에 존재하는 이미지(DockerHub 나 Private Repositoty 에서 다운로드)를 이용하는 방법이 있고, 이미지를 직접 만들어서 사용하는 방법(동일한 환경을 만들어서 사용하거나 애플리케이션을 배포

=>이미지를 생성하는 방법

-현재 사용중인 컨테이너를 이미지로 생성

-스크립트를 이용(Dockerfile)

=>IaC(Infrastructure as Code):인프라를 코드로 구성

-기존에는 하나의 개발팀이 개발을 하기 위해서 모여서 직접 동일한 버전의 소프트웨어를 설치해서 환경을 동일하게 생성

동일한 운영체제를 사용하거나 동일한 운영체제를 사용할 수 있는 VM을 이용

-리눅스 기반의 도커와 같은 컨테이너를 이용해서 동일한 환경을 만들어서 사용했는데 이 때 도커 환경을 구성을 하는 부분을 수동으로 하게 되면 서로 다른 환경이 만들어질 수 있어서 이를 코드로 만들어서 배포를 하고 각 개발자는 이 코드를 수행하기만 하면 동일한 환경을 만들 수 있습니다.

 

=>장점

-배포가 용이

-이미지가 어떻게 만들어졌는지 기록

-컨테이너 특정 작업을 자동으로 수행하도록 할 수 있음

 

2.작성

1)FROM:베이스 이미지 설정

2)MAINTAINER:이미지를 빌드한 작성자 이름과 이메일을 작성

=>필수는 아님

=>이미지에 오류가 발생하거나 이미지를 편집해서 다른 용도로 사용하고자 할 때 알림을 받기 위해서 작성

=>애플리케이션을 배포할 때 3단으로 이름을 만드는데 앞의 2개는 회사 도메인이나 개인의 경우 이메일을 역순으로 해서 작성


3)LABEL

=>이미지 작성 목적을 기재

=>필수는 아님

 

4)RUN

=>기본 이미지에 수행할 명령 작성

 

5)CMD

=>이미지를 컨테이너로 만들때 수행할 명령을 작성하거나 ENTRYPOINT 에 인자를 넘길 때 사용

=>CMD는 연속해서 여러개 작성하면 마지막 하나의 명령만 수행

 

6)ENTRYPOINT

=>이미지를 컨테이너로 만들 떄 수행할 명령을 작성하는데 CMD에서 매개변수를 받아서 명령을 수행할 수 있습니다

=>여러 개 연속 작성이 가능

 

7)COPY

=>호스트 컴퓨터의 내용을 복사할 때 사용

=>현재 작업 디렉토리의 내용만 복사가 가능

 

8)ADD

=>호스트 컴퓨터의 내용이나 URL을 이용해서 자원을 복사할때 사용

=>호스트 컴퓨터의 내용은 현재 작업 디렉토리의 내용만 복사 가능

 

9)ENV

=>환경 변수 설정에 사용

=>각 애플리케이션의 실행 옵션을 알아야 작성 가능

=>운영자 보다는 개발자가 작성하는 경우가 많음

 

10)EXPOSE

=>외부에 포트를 개방할 때 사용

=>포트 번호만 작성하기도 하고 포트번호/통신방식을 작성하기도 합니다.

EXPOSE 80

EXPOSE 80/tcp

 

11)VOLUME

=>호스트 컴퓨터나 도커 엔진에 공간을 만들어서 데이터를 저장하기 위한 개념

=>데이처의 반 영구적 저장이나 다른 컨테이너와의 데이터 공유를 위해서 사용

 

12)USER

=>기본 사용자는 root이고 다른 사용자를 추가하고자 하는 경우 사용

 

13)WORKDIR

=>현재 작업 디렉토리를 설정할 때 사용

 

14)ARG

=>변수의 값을 전달할 때 사용

=>변수의 값으로 전달하는 대표적인 값은 패스워드

=>CI/CD 를 구성할때 패스워드를 하드 코딩하면 빌드가 안되거나 계정이 정지되는 경우가 있습니다.

 

15)ONBUILD

=>이미지를 빌드할 때는 포함되지 않지만 해당 이미지가 다른 이미지의 기본 이미지로 사용될 떄 수행할 명령을 지정

 

16)STOPSIGNAL

=>도커 컨테이너가 중지될 떄 SIGTERM이라는 시그널을 전송하는데 이를 변경하고자 할 때 사용

 

17)SHELL

=>기본 셸 설정시 사용

 

3.명령어 작성 방법

=>FROM으로부터 시작

 

4.이미지 생성 명령

docker build [옵션] 생성할이미지이름 [:태그] dockerfile파일이 존재하는 디렉토리 경로

 

1)옵션

=>t:이미지에 태그를 지정하는 경우 사용

=>f: Dockerfile의 이름이 아닌 경우 직접 지정할때 사용

 

2)이미지 명

=>도커 허브에 업로드할 이미지라면 docker hub 이름/이미지이름:태그 형태가 되어야 하며 최신 버전에는 latest 라는 태그를 사용

 

3)경로

=>디렉토리 단위로 작성

=>이 디렉토리에는 필요한 자원 이외에는 아무것도 없어야 합니다.

=>COPY 명령이나 ADD 명령을 사용할 때 대부분의 경우.(현재디렉토리)로 설정

 

4)yml 파일 작성할 때 주의사항

=>키: 값

=>파이썬처럼 블럭은 들여쓰기를 사용하는데 하나의 블럭내에서는 일정한 간격을 사용하는데 보통은 2칸이나 4칸 - 탭 사용은 안됨

=>배열의 값을 표시할때 앞에 -를 추가

=>맨 앞에 ----이나 ...은 필수가 아니고 선택적

 

6.로컬 컴퓨터의 index.html을 welcome file로 사용하는 httpd이미지를 생성

 =>httpd는 apache web server 이미지이고 80번 포트와 443번 포트를 외부에 개발

=>Dockerfile 이 저장될 디렉토리 생성

=>생성항 디렉토리에 메인화면이 될 index.html 생성

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Dockerfile 사용</title>
</head>
<body>
  <h1>Dockerfile</h1>
  
</body>
</html>

 

=>Dockerfile 생성

#기본이미지 생성

FROM httpd

#현재 디렉토리에서는index.html파일을 컨테이너 내부의 htdocs에 복사

#apache 웹 서버는 htdocs의 index.html 을 welcome 파일( 도메인 또는 IP:포트번호 만으로 요청을 했을 때 보여지는 내용을 가진 파일)로 사용

COPY index.html /usr/local/apahce2/htdocs

 

=>이미지를 생성하는 명령 수행 -DockerFile 이 있는 디렉토리에서 작업하는것이 편리

docker build -t 이미지이름 Dockerfile 이 있는 디렉토리 경로

ex.) docker build -t apacheex .

 

=>이미지 확인

docker image ls 명령을 수행해도 되고 Docker Desktop에서 확인

 

7.Ubuntu 에서 PHP 웹페이지 연동

1)명령어 이용

=>우분투 컨테이너 실행:컨테이너 이름은 myweb 80번포트를 외부에선느 8095번 포트로 접속할 수 있도록 ubuntu 이미지를 이용해서 컨테이너 생성

docker run -dit --name myweb -p 8095:80 ubuntu

생성

 

=>컨테이너에 접속

docker exec -it myweb bash

bash shell 접속

 

=>apache2 서비스를 설치하고 서비스를 시작:기본 이미지는 최소로 설치되므로 다른 패키지 설치할 때 패키지 정보를 update 해야 합니다.

 

apt-get update

apt-get install apache2

service apache2 start

 

-패키지를 설치할 때 중간에 설치 여부를 확인하는 질문이 있고 y를 입력해야 설치가 됩니다

 

=>서비스 확인

브라우저에서 localhost:8095 로 접속

 

=>main 페이지를 변경하기 위해서 기존 메인 페이지의 이름을 수정:동일한 디렉토리에 다른 이름으로 이동을 시키면 이름을 변경한 효과

 

mv /var/www/html/index.html /var/www/html/index.html.org 

 

=>이름 변경 확인은

ls /var/www/html

 

=>vim  에디터 설치 - 명령문을 자동화할 때 대화식으로 수행되는 명령은 자동화가 불가

apt-get -y install vim

 

=>welcome 파일 작성

 

vim /var/www/html/index.html 명령을 이용해서 수행

<h1>Hello Docker File Practice <h1>

탈출하기 esc ->:wq!

 

=>브라우저에서 localhost:8095를 입력해서 변경 내용이 반영되었는지 확인

 

=>php 설치(소규모 웹사이트 작성에 가장 많이 사용되는 언어로 현재는 facebook이 php로 만들어져 있습니다)

apt-get-y install php

 

=>vim /var/www/html/index.php 명령으로 index.php 파일을 만들고 작성

 

=>브라우저에서 localhost:8095/index.php 로 접속하면 php 코드가 보여집니다

=>service apache2 restart 를 수행해서 apahce 웹 서버를 다시 구동

 

=>브라우저에서 localhost:8095/index.php  재시

html.css. javascript 는 정적인 웹 페이지를 만드는 기술로 브라우저가 해석합니다.

수정을 하면 새로고침만 하면 반영이 됩니다.

 

python, java(jsp),php, c#(asp.net),go 등의 프로그래밍 언어로 만드는 웹 애플리케이션은 브라우저가 해석하는것이 아니고 서버측에서 해석

이 부분을 수정을 하면 다시 구동해야 적용이 됩니다.

프로그래밍 언어는 컴파일을 하고 빌드를 다시 해야 변경 내용 적용 됩니다.

이 작업이 번거로워서 프로그래밍 언어로 만들되 호출할때 마다 새로 컴파일해서 출력을 만들어내는 방식이 jsp,asp.net 이나 template 기능을 사용하는 것입니다.

 

=>현재 컨테이너를 이미지 생성

docker commit 컨테이너이름 이미지이름

ex.) docker commit myweb myphpapp:1.0

 

 

2)Dockerfile 이용

=>디렉토리를 생성하고 dockerfile 생성

# 베이스 이미지 지정
FROM ubuntu:20.04

# 작성자 정보
LABEL maintainer="bkbk <wbk6108@naver.com>"

# 이미지 정보
LABEL description="IaC PHP Application"

# 베이스 이미지에 수행하는 명령
RUN apt-get -y update && \
    apt-get install -y tzdata && \
    apt-get install -y php && \
    apt-get install -y apache2 && \
    apt-get install -y git && \
    apt-get install -y curl && \
    apt-get install -y ssh && \
    apt-get install -y wget

# 환경변수 설정
ENV APACHE2_RUN_USER www-data
ENV APACHE2_RUN_GROUP www-data
ENV APACHE2_LOG_DIR /var/log/apache2
ENV APACHE2_WEB_DIR /var/www/html
ENV APACHE2_PID_FILE /var/run/apache2/apache2.pid

# 기본 웹 페이지를 생성
RUN echo 'Hello Docker Application' > /var/www/html/index.html

# PHP 페이지 생성
RUN echo '<?php phpinfo(); ?>' > /var/www/html/index.php

# 포트를 노출
EXPOSE 80

# 작업 디렉토리 설정
WORKDIR /var/www/html

# 이미지가 컨테이너로 만들어질 때 수행되는 명령
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

 

=>DockerFile 이 있는디렉토리에서 이미지 빌드

docker build -t myphpapp:3.0 .

 

=>만들어진 이미지를 가지고 컨테이너 생성

docker run -dit -p 8967:80 --name=phpapp3 myphpapp:3.0

 

=>확인

browser 에서 localhost:8967 로 접속

 

8.Dockerfile 작성시 유의 사항

=>docker build 명령을 통해 Dockerfile에 작성한 명령 순서대로 읽으면서 자동으로 이미지를 빌드하는데 이미지 빌드는 사용자 와의 대화식 처리가 아닌 자동화된 빌드

 

1)Ubuntu 에 python을 설치하는 도커 파일

FROM ubuntu:20.04

RUN apt-get install python

 

=>이미지 빌드

docker build -t myapp:1.0 .

 

=>에러

-리눅스의 기본 이미지는 최소로 만들어지기 때문에 패키지 정보가 없습니다.

-패키지 정보를 업데이트 하지 않으면 패키지 설치가 안됩니다.

 

2)도커 파일 수정

FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install python

 

=>이미지 빌드 

docker build -t myapp:1.0 .

 

=>에러

-이미지 빌드는 자동화된 작업인데 패키지를 설치할 떄 설치 여부를 묻는 대화창이 나오기 때문입니다.

-대화창이 나오는 명령일떄는 -y를 추가해서 설치해야합니다.

 

3)도커 파일 수정 (완)

FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y python

 

=>빌드 성공

 

4)캐시 이용

=>이미지를 빌드할때 이전에 사용한 레이어가 있으면 재사용

 

9.Programming언어로 만든 애플리케이션 배포를 위한 이미지 생성

1)python django 애플리케이션을 이미지로 만들기

=>python의 django 애플리케이션에서 기억해야 할 것

-python은 패키지를 설치하기 위한 패키지 목록 파일을 생성:일반적으로 이름은 requirements.txt

-django 실행 명령은 python manage.py runserver IP:포트번호

 

=>django 앱 만들기

-배포할 앱은 가상환경을 생성:환경과 함께 배포하는데 가상환경을 만들지 않으면 현재 컴퓨터에 설치된 모든 패키지를 전부 배포해야 합니다

 

=>가상환경 설치

pip install virtualenv

python3 -m venv ./myvenv(안되면 python3 을 python으로 수정해서 실행)

myvenv/Scripts/activate

 

=>django 실행

pip install django(장고 설치)

 

django-admin startproject dockerdjango(장고 프로젝트 생성)

 

cd dockerdjango

 

python manage.py runserver 0.0.0.0:8000(장고 실행)

=>패키지 목록을 텍스트 파일에 작성

pip freeze > requirements.txt

※가상환경을 만들지 않고 로컬에서 작성하면 모든 라이브러리가 다 freeze됨

 

 

=>프로젝트 안에 Dockerfile을 생성

FROM python

WORKDIR /usr/src/app

#패키지 목록 파일 복사해서 패키지 설치
COPY requirements.txt ./
RUN pip install -r requirements.txt

#현재 작업 디렉토리의 모든 파일 복사
COPY . .

EXPOSE 8000
#컨테이너로 만들어 질 때 이 명령을 수행해서 서버를 구동
CMD ["python","manage.py","runserver","0.0.0.0:8000"]

 

=>빌드

docker build -t dockerdjango .

성공!

 

=>이미지를 컨테이너로 싫행

docker run --name dockerdjango -dit -p 8000:8000 dockerdjango 

=>Docker Desktop 에서 컨테이너 실행 여부 확인 하던지 아니면 docker ps 명령으로 컨테이너 실행 여부 확인

 

=>브라우저에서 localhost:8000 으로 접속해서 확인

 

 

2)Spring Boot Application을 이미지로 만들기

=>react 나 spring boot 의 경우는 바로 배포를 하면 안되고 빌드를 해서 빌드된 내용을 배포해야 하는데 python의 코드는 읽으면서 실행하기 때문에 빌드를 할 필요가 없지만 react 나 spring boot는 source code를 실행 가능한 코드로 변경한 후 변경된 코드를 기반으로 실행을 합니다

 

 

10.git hub action을 docker hub에 자동 배포

1)git hub action

=>git hub의 repository 에 어떤 변화 발생시 작업을 자동으로 수행시킬수 있는 기능

-branch에 push나 merge 가 발생했을 때 배포를 자동으로 수행

git hub action 작성시 주의사항

비밀번호 같은 값들은 하드 코딩 하면 안되고, 반드시 secret을 사용해야 함.

 

2)go 프로그램을 작성하고 git hub action을 이용해서 배포

 

=>디렉토리 생성

 

gogithub 디렉토리 생성후 ->main.go 파일 생성

package main

import (
   "fmt"
   "time"
)

func main(){
   for{
      fmt.Println("Hello GO")
      time.Sleep(10 * time.Second)
   }
}

현재는 go가 설치되있지 않아서 build 하더라도 실행되지 않음.

하지만 도커파일을 활용하면 가능해짐

=>도커파일 생성

FROM golang:1.13-alpine as builder

RUN apk update && apk add git

WORKDIR /usr/src/app

#현재 디렉토리의 모든 것을 WORKDIR로 복사함 main.go가 복사될 것.
COPY . .

#GO 실행 명령
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -ldflags '-s' -o main .

FROM scratch

COPY --from=builder /usr/src/app .

CMD ["/main"]

=>이미지 생성

docker build -t goapp:1.0 .

 

=>컨테이너로 생성해서 실행

docker run --name goapp-deploy goapp:1.0

 

=>github에 코드 업로드

-git hub에 repository 생성 (godockerhub)

 

-로컬에서 push

 

git init

git add .

git commit -m "1"

git remote add origin githuburl

git push origin main

- 이 과정에서 403 에러가 나는 경우

이경우는 로그인 에러이므로 github에서 token을 발급받아야함

git remote set-url origin https://<자기 github이름>@github.com/<자기github 이름>/ <레포지토리 이름>.git 으로 설정한 후 다시 git push origin main을 하면 비밀번호를 넣으라고 하는데 이 때  발급받은 토큰 입력해주면 됩니다.

 

=>Docker Hub에 로그인해서 레포지토리를 생성

이름:원하는이름

토큰:"복사해놔야함"

레포지토리:godockerhub

 

=>git hub action을 작성하는 방법

-프로젝트에 .github/workflows 디렉토리 안에 yml 파일을 만드는 방법

-git hub의 repositoty 에서 git hub action 파일을 추가

 

=>자기 프로젝트에 .github/workflows 디렉토리를 생성(파일 이름은 아무런 의미가 없고 디렉토리 이름이 중요)

 

=>yaml 파일 생성

name: GODOCKERHUB

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v3
      - name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: 1.15
      - name: Build
        run: go build -v ./...

      # Docker Hub Deployment
      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{secrets.DOCKERHUB_USERNAME}}
          password: ${{secrets.DOCKERHUB_TOKEN}}
       
      - name: Build and Release to DockerHub
        env:
          NAME: byeoungkwon
          REPO: godockerhub
        run: |
          docker build -t $REPO .
          docker tag $REPO:latest $NAME/$REPO:latest
          docker push $NAME/$REPO:latest

=>GITHUB ACTION에 사용하는 키를 생성

-레포지토리에서 settings 를 클릭

[Security] - [Secrets and variables]-[Actions] 클릭한후 변수를 추가

[New Repository secret]을 추가해서 key값 추가

key값들 추가

git add .

git commit -m "bkbk"

git push origin main

하면 dockerhub 까지 자동 등록됨

 

3)django application을 DOCKERHUB에 자동 배포

=>동작하는 장고 프로그램을 작성

-가상환경 생성 패키지 설치:pip install virtualenv

-가상환경 생성:python -m venv ./myvenv

-가상환경 활성화: myvenv/Scripts/activate

-장고 패키지 설치:pip install django

-장고 프로젝트 생성:django-admin startproject djangodockerhub

 

-프롬프트를 프로젝트로 이동

cd djangodockerhub

 

-코드 작성

 

-실행 확인

python manage.py runserver 0.0.0.0:80

-브라우저에서 localhost입력하고 동작하는지 확인

-현재 사용한 패키지 목록을 텍스트 파일에 내보내기

pip freeze >requirements.txt

 

 

=>Dockerfile 파일을 만들어서 이미지 빌드가 되고  컨테이너 생성되서 동작하는지 확인

FROM python

WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install -r requirements.txt
copy . .

EXPOSE 80
#python 프로젝트는 이 부분만 변경
CMD ["python","manage.py","runserver","0.0.0.0:80"]

 

-이미지 빌드

docker build -t djangodockerhub .

완성

-컨테이너를 만들어서 확인

docker run --name=djangodockerhub -p 80:80 -d djangodockerhub

-브라우저에서 localhost 로 접속해서 장고로고가 보이는지 확인

 

-애플리케이션 작업 종료

 

=>DockerHub 에 레포지토리 생성

-유저 이름: byeoungkown

 

-레포지토리 이름(이미지마다 하나씩 생성):djangodockerhub

 

-access token(1번만 발급받으면 됩니다)

 

=>GIT HUB와 장고 프로그램 연결

-github에 repository 생성:https://github.com/KingBKwon/djangodocker

-프로젝트 프롬프트에서 수행

git init

git add .

git commit -m "메세지"

git remote add origin https://github.com/KingBKwon/djangodocker

git push origin main

#보안 상의 문제로 push 가 안되는 경우 아래처럼 작성한 후 나중에 git hub 토큰값을 입력

#KINGBKwon은 github이름 djangodockerhub위치는 레포지토리 이름입니다.

안되면 git remote set-url origin https://KingBKwon@github.com/KingBKwon/djangodockerhub(레포지토리이름).git 

=>GIT HUB Action 파일을 만들어서 푸시를 할 때 DOCKER HUB 에 업로드 되는지 확인

-프로젝트에 .github/workflows 디렉토리를 생성하고 yml 파일을 생성

name: django

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3
     
      # 파이썬 세팅
      - name: Set up Python 3.10
        uses: actions/setup-python@v2
        with:
          python-version: '3.10'
     
      - name: Install Dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
     
      # 도커 허브 관련 설정
      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
     
      # 도커 허브 배포
      - name: Build and Release to DockerHub
        env:
          NAME: ${{ secrets.DOCKERHUB_USERNAME }}
          REPO: djangodockerhub
        run: |
          docker build -t $REPO .
          docker tag $REPO:latest $NAME/$REPO:latest
          docker push $NAME/$REPO:latest

 

-git push를 하고 확인

git push origin main

 

=>업로드 된 이미지를 가지고 컨테이너를 생성해서 실행(이 부분은 나중에 클라우드에 배포하는 걸로 변경)

docker run --name djangodockerhub -p 80:80 -dit byeoungkwon/djangodockerhub

 

브라우저에 localhost로 접속해서 장고로고가 보여지는지 확인

성공!

이제 git 에 push만 하면 자동으로 배포가 됨. 이게 CI/CD

'Study > Cloud,Docker,Kubernetes' 카테고리의 다른 글

Kubernetes  (0) 2024.04.08
Docker(4)-DockerCompose  (0) 2024.04.06
Docker(2)  (0) 2024.04.03
Docker(1)  (0) 2024.04.02
Cloud(1)-개요  (0) 2024.04.01