[Docker] Docker 응용 (1)

Bzeromo·2025년 5월 20일
0

Infra, DevOps, MSA

목록 보기
26/28
post-thumbnail

🐳 Docker 응용 (1)


💡 CLI가 까다롭다면 가상환경을 vscode에서 원격으로 열어서
그 안에 Docker 확장을 받아 사용합시다!

📌 Dockerfile

Docker 이미지를 빌드하는 데 사용되는 텍스트 파일

  • 이미지를 빌드하는 데 필요한 모든 지침이 포함되어 있음

  • 이 지침에는 기본 이미지, 설치할 소프트웨어, 실행할 명령, 환경 변수 설정 등이 포함

  • Dockerfile을 이용하면 애플리케이션을 컨테이너화하고 배포하거나, 개발 환경을 설정하고 공유할 수 있음

  • 또한, CI/CD 파이프라인을 자동화하고 이미지 빌드 및 배포 프로세스를 간소화할 수 있음

⚓ Dockerfile 장점

🔴 재현성: Dockerfile을 사용하면 동일한 이미지를 여러 번 빌드할 수 있으며, 매번 동일한 결과를 얻을 수 있음

🔴 자동화: Dockerfile을 사용하여 이미지 빌드 프로세스를 자동화할 수 있음

🔴 공유: Dockerfile을 쉽게 공유하여 다른 사람들이 이미지를 빌드하고 사용하게 할 수 있음

🔴 버전 관리: Dockerfile을 버전 관리 시스템에 저장하여 이미지 빌드 프로세스를 추적하고 변경 사항을 롤백할 수 있음

⚓ Dockerfile 구문 구조

  • 기본 이미지 지정

    FROM <image> [: <tag>]

  • 이미지 빌드 지침
    … …

  • 컨테이너 시작시 실행할 명령

    CMD ["executeable", "param1", "param2"]

    명령어설명
    FROM베이스 이미지 지정 (필수)
    RUN쉘 명령어 실행 (패키지 설치 등)
    COPY호스트 파일/폴더를 이미지에 복사
    ADD파일 복사 (압축 해제 등 추가 기능 포함)
    WORKDIR작업 디렉토리 설정
    ENV환경 변수 설정
    EXPOSE컨테이너에서 열 포트 지정
    CMD컨테이너 시작 시 기본으로 실행할 명령어 지정
    ENTRYPOINT컨테이너 시작 시 반드시 실행할 명령어 지정
    LABEL이미지에 메타데이터(key-value) 추가

⚓ Dockerfile 모범 사례

  • Dockerfile 지시문은 대문자로 작성

  • 각 지시문은 한 줄에 하나씩 작성

  • #문자를 사용하여 주석 추가

  • 가능하면 레이어 수를 최소화하여 이미지 크기 최대한 축소

  • 컨텍스트 크기를 최소화하여 빌드 시간 단축

  • 캐시 가능한 레이어를 활용하여 빌드 속도 가속

  • 레이어 수 최소화

    • 가능한 한 명령어를 하나의 RUN 명령으로 결합하여 레이어 수 줄임

    • && 연산자를 사용하여 여러 명령어를 하나의 RUN으로 묶음

    • 불필요한 패키지 설치 및 임시

  • 적절한 베이스 이미지 선택

    • 대부분의 경우 Alpine 베이스 이미지 사용 시 이미지 크기를 최소화할 수 있음

    • 특정 용도에 맞는 공식 베이스 이미지 선택 (예: Node.js용 node 이미지)

  • 레이어 캐싱 활용

    • 가능한 한 변경되지 않는 명령어를 Dockerfile의 상단에 배치하여 캐싱 최대화

    • 자주 변경되는 명령어는 Dockerfile 하단에 배치

  • 멀티스테이지 빌드 사용

    • 빌드 단계와 실행 단계를 분리하여 불필요한 의존성 제거

    • 결과물만 최종 이미지에 포함하여 이미지 크기 줄임

  • 환경변수와 ARG 활용

    • ENV 명령어로 환경변수를 설정하여 Dockerfile을 유연하게 작성

    • ARG 명령어로 빌드 시간 변수를 설정하여 빌드 과정 최적화

  • 불필요한 패키지 제거

    • apt-get install --no-install-recommends 옵션을 사용하여 불필요한 패키지 설치 방지

    • apt-get autoremoverm -rf /var/lib/apt/lists/*를 사용하여 임시 파일과 패키지 제거

  • 최신 패키지와 업데이트 유지

    • 항상 최신 패키지와 업데이트를 사용하여 보안 취약점 방지

    • apt-get update 및 apt-get upgrade 등의 명령어 사용

  • 적절한 사용자와 권한 설정

    • 최소 권한의 원칙을 따르고 루트 사용자 대신 비루트 사용자 사용

    • 컨테이너 내부에서 필요한 최소한의 권한만 부여

  • Dockerignore 파일 사용

    • Dockerfile과 함께 .dockerignore 파일을 사용하여 불필요한 파일이나 디렉토리를 제외하여 이미지 크기 최소화

⚓ 멀티스테이지

  • 도커 이미지 생성시, 여러 단계의 빌드를 사용하여 이미지 크기를 최적화하는 기법

  • 단일 Dockerfile 내에서 여러 FROM 지시문을 사용하여 여러 단계를 정의하고,

  • 각 단계에서 필요한 파일과 의존성만을 포함하여 최종 이미지의 크기를 줄일 수 있음

  • 이를 통해 개발 및 배포 프로세스를 효율적으로 관리할 수 있음


📌 도커 네트워킹

  • 네트워크란 두 대 이상의 장치가 물리적 또는 가상으로 서로 통신할 수 있도록 구성된 집합을 의미
  • 도커 네트워크는 도커가 컨테이너 간 통신을 가능하게 하기 위해 생성하는 가상 네트워크
  • 동일한 호스트에서 실행 중인 두 컨테이너는 호스트 머신에 포트를 노출하지 않아도 서로 통신할 수 있음

⚓ 도커 네트워크 드라이버

  • 컨테이너 간 통신 방식과 네트워크 환경을 결정하는 핵심 요소
  • 다양한 환경과 요구에 맞춰 컨테이너 네트워크를 유연하게 설계할 수 있도록 지원
드라이버특징 및 용도
bridge도커의 기본 네트워크 드라이버로, 하나의 호스트 내에서 컨테이너 간 격리된 네트워크 제공. docker0라는 가상 브리지를 통해 컨테이너 연결. 동일 브리지 네트워크 내에서는 통신 가능하나, 외부와 통신하려면 포트 매핑 필요.
host컨테이너가 호스트의 네트워크 스택을 직접 사용. 격리가 없으며, 컨테이너가 호스트와 동일한 IP와 포트를 사용함. 성능이 중요한 경우에 사용하지만, 포트 충돌 및 보안상 주의 필요.
none컨테이너에 네트워크 인터페이스를 할당하지 않음. 네트워크가 완전히 비활성화된 상태로 외부와의 통신이 필요 없는 특수 목적이나 커스텀 네트워크 드라이버와 함께 사용.
overlay여러 도커 호스트 간 컨테이너 네트워크를 구성할 때 사용. 도커 스웜(Swarm) 등 클러스터 환경에서 컨테이너가 서로 다른 서버에 있어도 하나의 네트워크처럼 통신 가능.

🖥 도커 네트워크 생성

# 도커 네트워크 생성
docker network create mynetwork
docker network ls

💡 docker network inspect [네트워크명] 으로 ip가 네트워크마다 다름을 확인할 수 있다.

🖥 도커 네트워크 활용 컨테이너 생성

# 네트워크 활용 컨테이너 생성
docker run -d --name mariadb01a \
-e MARIADB_ROOT_PASSWORD=bzeromo \
-e MARIADB_DATABASE=bzeromo \
-e MARIADB_USER=bzeromo \
-e MARIADB_PASSWORD=bzeromo \
--network mynetwork \
-p 4306:3306 mariadb:10.11.11

mariadb -u bzeromo -P 4306 -p bzeromo

🖥 도커 네트워크로 컨테이너끼리 연결

vi ~/vols/tomcat/html/index.jsp
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Statement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>MariaDB Connection Test</title>
</head>
<body>
<%
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    String url = "jdbc:mariadb://mariadb01a:3306/bzeromo";
    String id = "bzeromo";
    String pw = "bzeromo";
    try {
        Class.forName("org.mariadb.jdbc.Driver");
        conn = DriverManager.getConnection(url, id, pw);
        stmt = conn.createStatement();
        rs = stmt.executeQuery("SELECT NOW()");
        if(rs.next()) {
            out.println("DB 접속 성공! 현재 시간: " + rs.getString(1));
        }
    } catch(Exception e) {
        out.println("DB 접속 실패: " + e.getMessage());
    } finally {
        if(rs != null) try { rs.close(); } catch(Exception e) {}
        if(stmt != null) try { stmt.close(); } catch(Exception e) {}
        if(conn != null) try { conn.close(); } catch(Exception e) {}
    }
%>
</body>
</html>
mkdir -p ~/vols/tomcat/lib
cp ~/dockerfile/tomcat/mariadb*.jar ~/vols/tomcat/lib/

docker run -d --name tomcat01a \
--network mynetwork \
-v ~/vols/tomcat/html:/usr/local/tomcat/webapps/ROOT \
-p 9099:8080 \
tomcat:10.1.41-jdk17-temurin-jammy

docker cp ~/dockerfile/tomcat/mariadb*.jar \
tomcat01a:/usr/local/tomcat/lib/

docker restart tomcat01a
curl localhost:9099

profile
Hodie mihi, Cras tibi

0개의 댓글