Docker Introduction

Docker

์ปจํ…Œ์ด๋„ˆ๋ผ๋Š” ํŒจํ‚ค์ง€๋กœ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋Š” ํˆด๋กœ ์„œ๋กœ ๊ฒฉ๋ฆฌ๋œ ํ™˜๊ฒฝ์—์„œ ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ๊ณผ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ์šด์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

Docker Image

์„ค์ •๋œ ํ™˜๊ฒฝ์˜ ์Šค๋ƒ…์ƒท์œผ๋กœ, ๋™์ผํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๊ตฌ๋™๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜์—ฌ ์žฌํ˜„์„ฑ์„ ๋ณด์žฅ

๋ฐ์ดํ„ฐ ์—”์ง€๋‹ˆ์–ด๊ฐ€ Docker ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ์ด์œ 

  • ์žฌํ˜„ ๊ฐ€๋Šฅ์„ฑ์„ ์ œ๊ณต
  • ๋ณต์žกํ•œ ํŒŒ์ดํ”„๋ผ์ธ์˜ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ
  • Ci/CD๋ฅผ ํ†ตํ•œ ์†Œํ”„ํŠธ์›จ์–ด ๊ณตํ•™ ์‹คํ˜„
  • ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์˜์กด์„ฑ ์ œ๊ณต
  • ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์˜ ์‹คํ—˜ ์ œ๊ณต
ํšจ๊ณผ
  • Test๋ฅผ ์œ„ํ•œ ๋กœ์ปฌ ์„ธํŒ…
  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ, CI/CD
  • ๋ฐฐ์น˜ ์ž‘์—…
  • Spark ์‚ฌ์šฉ
  • ์„œ๋ฒ„๋ฆฌ์Šค (AWS Lambda)

ํ•ด๋‹น ๊ฐ•์˜์—์„œ๋Š” Docker๋ฅผ ํ†ตํ•œ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์„ฑ์„ ๋ชฉ์ ์œผ๋กœ Docker๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.

Pipeline Overview

Docker์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

๊ธฐ๋ณธ ์ž‘์„ฑ ๋ฐฉ๋ฒ•

๋„์ปค๋ฅผ ํ†ตํ•ด ํŒŒ์ด์ฌ์˜ pandas๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •
FROM python:3.9
RUN pip install pandas
ENTRYPOINT [ "bash" ]
docker build -t test:pandas .
๋กœ์ปฌ์˜ ํŒŒ์ผ์„ ํฌํ•จํ•ด์„œ Docker ์ด๋ฏธ์ง€ ์ƒ์„ฑ
FROM python:3.11.9-slim
RUN pip install pandas
WORKDIR /app
COPY pipeline.py pipeline.py
ENTRYPOINT [ "bash" ]
docker build -t test:pandas
docker run -it test:pandas

Docker

docker -it๋Š” Docker ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒํ˜ธ์ž‘์šฉ ๋ชจ๋“œ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

  • i : ํ‘œ์ค€ ์ž…๋ ฅ(sddin)์„ ์—ด์–ด ์ปจํ…Œ์ด๋„ˆ์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ
  • t : ๊ฐ€์ƒ ํ„ฐ๋ฏธ๋„์„ ํ• ๋‹ค์•ป ํ„ฐ๋ฏธ๋„ ์„ธ์…˜์„ ์—๋ฎฌ๋ ˆ์ดํŠธ ํ•˜๋Š” ๊ฒƒ docker run -it <Image Name>
์ปจํ…Œ์ด๋„ˆ์— ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ
FROM python:3.11.9-slim
RUN pip install pandas
WORKDIR /app 
COPY pipeline.py pipeline.py
ENTRYPOINT [ "python", "pipeline.py" ]
import sys

import pandas

print(sys.argv)

day = sys.argv[1] # '2020-01-01'

# some fancy stuff with pandas

print(f'job finished successfully for day = {day}')

buildํ›„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์–ด๋กœ ์ฒ˜๋ฆฌ

docker run -it test:pandas 2025-01-18 ['pipeline.py', '2025-01-18']

>> job finished successfully for day = 2025-01-18

NY ํƒ์‹œ ๋ฐ์ดํ„ฐ Postgres์— ์ˆ˜์ง‘

Docker์‚ฌ์šฉํ•œ Postgres ๋ช…๋ น์–ด

์‚ฌ์ „์ž‘์—…
1. pgcli
pip install pgcli
2. PostgreSQL ์‹คํ–‰
pgcli -h localhost -p 5432 -u root -d ny_taxi
3. Jupyter Notebook ์‹คํ–‰
4. ํƒ์‹œ ๋ฐ์ดํ„ฐ ๋‹ค์šด๋กœ๋“œ

Dataset:

pgAdmin๊ณผ Postgres ์—ฐ๊ฒฐ

while๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•ด CSV๋ฅผ ์ฒญํฌ ๋‹จ์œ„๋กœ ์‚ฝ์ž…
from time import time
while True:
	t_start = time()
	df = next(df_iter) df.tpep_pickup_datetime = pd.to_datetime(df.tpep_pickup_datetime)
	df.tpep_dropoff_datetime = pd.to_datetime(df.tpep_dropoff_datetime)
	df.to_sql(name='yellow_taxi_data', con=engine, if_exists='append')
	print('.', end='')
	
	t_end = time()
	
	print('inserted another chunk..., took: %.3f seconds' % (t_end - t_start))
pgAdmin ์‹คํ–‰

๋„์ปค ๋ช…๋ น์„ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

docker run -it \ -e PGADMIN_DEFAULT_EMAIL="admin@admin.com" \ -e PGADMIN_DEFAULT_PASSWORD="root" \ -p 8080:80 \ dpage/pgadmin4

์ˆ˜์ง‘ ์Šคํฌ๋ฆฝํŠธ ๋„์ปคํ™”

์ฃผํ”ผํ„ฐ ๋…ธํŠธ๋ถ์„ ํŒŒ์ด์ฌ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ณ€ํ™˜

nbconvert ์„œ๋ธŒ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ด์„œ Notebook์„ ํŒŒ์ด์ฌ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

jupyter nbconvert --to=script upload-data.ipynb

[NbConvertApp] Converting notebook upload-data.ipynb to script [NbConvertApp] Writing 3466 bytes to upload-data.py

Dockerizing ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

  • ๋ฐ์ดํ„ฐ Ingestion์„ ์œ„ํ•ด pandas๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋กœ์ปฌ์˜ PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๋Š” ๊ณผ์ •
  • ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ์œ„ํ•œ username, password, host, port ๋“ฑ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •
  • OS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด CSVํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ
#!/usr/bin/env python
# coding: utf-8

import os
import argparse

from time import time

import pandas as pd
from sqlalchemy import create_engine


def main(params):
    user = params.user
    password = params.password
    host = params.host 
    port = params.port 
    db = params.db
    table_name = params.table_name
    url = params.url
    
    # the backup files are gzipped, and it's important to keep the correct extension
    # for pandas to be able to open the file
    if url.endswith('.csv.gz'):
        csv_name = 'output.csv.gz'
    else:
        csv_name = 'output.csv'

    os.system(f"wget {url} -O {csv_name}")

    engine = create_engine(f'postgresql://{user}:{password}@{host}:{port}/{db}')

    df_iter = pd.read_csv(csv_name, iterator=True, chunksize=100000)

    df = next(df_iter)

    df.tpep_pickup_datetime = pd.to_datetime(df.tpep_pickup_datetime)
    df.tpep_dropoff_datetime = pd.to_datetime(df.tpep_dropoff_datetime)

    df.head(n=0).to_sql(name=table_name, con=engine, if_exists='replace')

    df.to_sql(name=table_name, con=engine, if_exists='append')


    while True: 

        try:
            t_start = time()
            
            df = next(df_iter)

            df.tpep_pickup_datetime = pd.to_datetime(df.tpep_pickup_datetime)
            df.tpep_dropoff_datetime = pd.to_datetime(df.tpep_dropoff_datetime)

            df.to_sql(name=table_name, con=engine, if_exists='append')

            t_end = time()

            print('inserted another chunk, took %.3f second' % (t_end - t_start))

        except StopIteration:
            print("Finished ingesting data into the postgres database")
            break

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Ingest CSV data to Postgres')

    parser.add_argument('--user', required=True, help='user name for postgres')
    parser.add_argument('--password', required=True, help='password for postgres')
    parser.add_argument('--host', required=True, help='host for postgres')
    parser.add_argument('--port', required=True, help='port for postgres')
    parser.add_argument('--db', required=True, help='database name for postgres')
    parser.add_argument('--table_name', required=True, help='name of the table where we will write the results to')
    parser.add_argument('--url', required=True, help='url of the csv file')

    args = parser.parse_args()

    main(args)

์œ„ ํŒŒ์ด์ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ์˜ Dockering Injsetion Script ์ž‘์„ฑ ๊ฐ€๋Šฅ

FROM python:3.11.9-slim

RUN apt-get update && apt-get install -y wget
RUN pip install pandas sqlalchemy psycopg2-binary

WORKDIR /app

COPY ingest_data.py ingest_data.py

ENTRYPOINT [ "python", "ingest_data.py" ]

์ดํ›„ ๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ ์‹œ์ผœ ์ฒ˜๋ฆฌ

URL="https://github.com/DataTalksClub/nyc-tlc-data/releases/download/yellow/yellow_tripdata_2021-01.csv.gz"

docker run -it \
  --network=pg-network \
  taxi_ingest:v001 \
    --user=root \
    --password=root \
    --host=pg-database \
    --port=5432 \
    --db=ny_taxi \
    --table_name=yellow_taxi_trips \
    --url=${URL}	

๋„์ปค๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€ ์ €์žฅ ์ „์— HTTP ์„œ๋ฒ„๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌ

Docker Compose์ด์šฉํ•œ ์„œ๋น„์Šค ๊ตฌ์„ฑ

Docker Compose

์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ์˜ ๊ตฌ์„ฑ์„ ํ•œ๋ฒˆ์— ์ •๋ฆฌํ•˜๊ณ  ๊ด€๋ฆฌ, ์‹คํ–‰

๋ธ”๋กœ๊ทธ : https://data-newbie.tistory.com/930#deployments ์„ค์น˜ ๊ณผ์ • : https://docs.docker.com/compose/install/

Postgres ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ PgAdmin์„ค์ •

services:
  pgdatabase:
    image: postgres:13
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=root
      - POSTGRES_DB=ny_taxi
    volumes:
      - ./ny_taxi_postgres_data:/var/lib/postgresql/data:rw
    ports:
      - "5432:5432"    
  pgadmin:
    image: dpage/pgadmin4
    environment:
      - PGADMIN_DEFAULT_EMAIL=admin@admin.com
      - PGADMIN_DEFAULT_PASSWORD=root
    ports:
      - "8080:80"
  • Postgres์˜ ํฌํŠธ : 5432๋กœ ์„ค์ • ํ›„ ์ปจํ…Œ์ด๋„ˆ์—์„œ๋„ ๊ฐ™์€ ํฌํŠธ๋กœ ๋งคํ•‘
  • pgAdmin์„ ์„ค์ • ์‹œ, env ์„ค์ • ๋ฐ ํฌํŠธ 8080 โ†’ 80์œผ๋กœ ๋งคํ•‘
  • docker compose up ์„ ํ†ตํ•ด ์‹คํ–‰
  • docker compose down์„ ํ†ตํ•ด ์ปจํ…Œ์ด๋„ˆ ์ค‘์ง€
Docker Compose ์žฅ์ 
  • ๋„คํŠธ์›Œํฌ ์ˆ˜๋™ ์ƒ์„ฑ ํ•„์š” x
  • Detached mode๋กœ ์‹คํ–‰ํ•˜์—ฌ ํ„ฐ๋ฏธ๋„์„ ๋‹ค์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ 
  • docker compose down ์œผ๋กœ ์—ฌ๋Ÿฌ ํ„ฐ๋ฏธ๋„ ์ฐฝ์„ ๋ณด์ง€ ์•Š๊ณ  ํ•œ ๋ฒˆ์— ์ข…๋ฃŒ ๊ฐ€๋Šฅ
  • ๋กœ์ปฌ ์„ธํŒ…, ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์— ์œ ์šฉ

[pgadmin์—์„œ์˜ ํ…Œ์ŠคํŠธ ์ฟผ๋ฆฌ ์‹คํ–‰]

GCP

Google์—์„œ ์ œ๊ณตํ•˜๋Š” ํด๋ผ์šฐ๋“œ ์ปดํ“จํŒ… ์„œ๋น„์Šค๋กœ ๋‹ค์–‘ํ•œ ์ปดํ“จํŒ…, ์Šคํ† ๋ฆฌ์ง€, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ํ˜ธ์ŠคํŒ… ์„œ๋น„์Šค๊ฐ€ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

Terraform

HashiCorp์˜ ์˜คํ”ˆ์†Œ์Šค ๋„๊ตฌ๋กœ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํด๋ผ์šฐ๋“œ ์ธํ”„๋ผ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์œผ๋กœ ๊ฑด๋ฌผ์„ ์ง“๋“ฏ์ด, Terraform ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์„œ๋ฒ„, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ๋„คํŠธ์›Œํฌ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ์ž์›๋“ค์„ ์ •์˜ํ•˜๊ณ  ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠน์ง•
  • ์ธํ”„๋ผ ์ˆ˜๋ช… ์ฃผ๊ธฐ ๊ด€๋ฆฌ
  • ๋ฒ„์ „ ์ œ์–ด ์ปค๋ฐ‹
  • ์Šคํƒ ๊ธฐ๋ฐ˜ ๋ฐฐํฌ์— ๋งค์šฐ ์œ ์šฉํ•˜๋ฉฐ AWS, GCP, Azure, K8S์™€ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ๊ณต๊ธ‰์ž์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐฐํฌ ์ „๋ฐ˜์— ๊ฑธ์ณ ๋ฆฌ์†Œ์Šค ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•œ ์ƒํƒœ ๊ธฐ๋ฐ˜ ์ ‘๊ทผ ๋ฐฉ์‹
์‚ฌ์šฉํ•˜๋Š” ์ด์œ 
  • ์ธํ”„๋ผ ์ถ”์ ์˜ ๋‹จ์ˆœํ™”
  • ๋” ์‰ฌ์šด ํ˜‘์—…
  • ์žฌํ˜„์„ฑ
  • ๋ฆฌ์†Œ์Šค ์ œ๊ฑฐ ๋ณด์žฅ

ํ…Œ๋ผํผ ์ž‘๋™ ๋ฐฉ์‹

Terraform์€ ์ฝ”๋“œํ˜• ์ธํ”„๋ผ(IaC) ๋„๊ตฌ๋กœ, ์ธํ”„๋ผ๋ฅผ ์„ ์–ธ์  ๊ตฌ์„ฑ ํŒŒ์ผ๋กœ ์ •์˜ํ•˜๊ณ  ํ”„๋กœ๋น„์ €๋‹ ๋ฐ ๊ด€๋ฆฌ

Terraform Core โ€ข Terraform์˜ ํ•ต์‹ฌ ์š”์†Œ๋กœ, RPC(์›๊ฒฉ ํ”„๋กœ์‹œ์ € ํ˜ธ์ถœ)๋ฅผ ํ†ตํ•ด ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ํ†ต์‹ . ์ฃผ์š” ์—ญํ•  โ€ข ๊ตฌ์„ฑ ํŒŒ์ผ ์ฝ๊ธฐ ๋ฐ ์ข…์†์„ฑ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ. โ€ข ๋ฆฌ์†Œ์Šค ์ƒํƒœ ๊ด€๋ฆฌ(terraform.tfstate ํŒŒ์ผ). โ€ข ๊ณ„ํš ์‹คํ–‰(terraform plan) ๋ฐ ์ ์šฉ(terraform apply).

Terraform Plugin โ€ข ์™ธ๋ถ€ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ ๊ตฌํ˜„๋œ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ, ํŠน์ • ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž์™€ ํ†ต์‹ . ์ฃผ์š” ์—ญํ•  โ€ข API ํ˜ธ์ถœ์„ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ/์ˆ˜์ •/์‚ญ์ œ(CRUD) ์ฒ˜๋ฆฌ. โ€ข ์ธ์ฆ ๋ฐ ์„œ๋น„์Šค ๋งคํ•‘.

State Management โ€ข Terraform์€ ๋ฆฌ์†Œ์Šค์˜ ์ƒํƒœ๋ฅผ .tfstate ํŒŒ์ผ์— ์ €์žฅํ•˜์—ฌ ์ธํ”„๋ผ์™€ ์ฝ”๋“œ ๊ฐ„์˜ ๋™๊ธฐํ™”๋ฅผ ์œ ์ง€. โ€ข ์ƒํƒœ ํŒŒ์ผ์€ ๋ฆฌ์†Œ์Šค ๊ฐ„ ์ข…์†์„ฑ์„ ์ถ”์ ํ•˜๋ฉฐ, ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”.

Declarations
  1. terraform โ€ข ๊ธฐ๋ณธ ์„ค์ •์„ ์ •์˜ํ•˜๋ฉฐ, ์ธํ”„๋ผ๋ฅผ ํ”„๋กœ๋น„์ €๋‹ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. โ€ข ์ฃผ์š” ์†์„ฑ: โ€ข required_version: Terraform ๋ฒ„์ „ ์š”๊ตฌ์‚ฌํ•ญ. โ€ข backend: ์ƒํƒœ ํŒŒ์ผ ์ €์žฅ ์œ„์น˜ ์ง€์ •(์˜ˆ: local, remote). โ€ข required_providers: ์‚ฌ์šฉํ•ด์•ผ ํ•  ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž ์„ค์ •.
  2. provider โ€ข Terraform์ด ๊ด€๋ฆฌํ•  ๋ฆฌ์†Œ์Šค ์œ ํ˜•๊ณผ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ชจ๋“ˆ. โ€ข ์˜ˆ: AWS, Google Cloud, Azure ๋“ฑ.
  3. resource โ€ข ์ธํ”„๋ผ์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ธ”๋ก. โ€ข ์˜ˆ: aws_instance, google_storage_bucket.
  4. variable & locals โ€ข variable: ๋Ÿฐํƒ€์ž„ ์‹œ ๋™์ ์œผ๋กœ ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ์ž…๋ ฅ ๋ณ€์ˆ˜. โ€ข locals: ๊ณ ์ •๋œ ๊ฐ’์ด๋‚˜ ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๋กœ์ปฌ ๋ณ€์ˆ˜.
ํŒŒ์ผ ๊ตฌ์„ฑ
  1. main.tf: Terraform์˜ ๋ฉ”์ธ ๊ตฌ์„ฑ ํŒŒ์ผ๋กœ, ๋ฆฌ์†Œ์Šค์™€ ์ œ๊ณต์ž๋ฅผ ์ •์˜.
  2. variables.tf: ๋ณ€์ˆ˜ ์„ ์–ธ ๋ฐ ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •.
  3. resources.tf: ๋ฆฌ์†Œ์Šค ๋ธ”๋ก์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ž‘์„ฑ(์„ ํƒ ์‚ฌํ•ญ).
  4. output.tf: ์ƒ์„ฑ๋œ ๋ฆฌ์†Œ์Šค์˜ ์ถœ๋ ฅ๊ฐ’์„ ์ •์˜(์„ ํƒ ์‚ฌํ•ญ).
  5. .tfstate: ํ˜„์žฌ ์ธํ”„๋ผ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” ํŒŒ์ผ.
Terraform ์ž‘๋™ ํ๋ฆ„
  1. Write: ์„ ์–ธ์  ๊ตฌ์„ฑ ํŒŒ์ผ ์ž‘์„ฑ(main.tf, variables.tf ๋“ฑ).
  2. Plan: ํ˜„์žฌ ์ƒํƒœ์™€ ์›ํ•˜๋Š” ์ƒํƒœ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ณ„ํš(terraform plan).
  3. Apply: ๊ณ„ํš๋œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์‹ค์ œ๋กœ ์ ์šฉ(terraform apply).
  4. Destroy: ๊ธฐ์กด ์ธํ”„๋ผ๋ฅผ ์‚ญ์ œ(terraform destroy).
์ฃผ์š” ๋ช…๋ น์–ด
  1. terraform init: Terraform ํ”„๋กœ์ ํŠธ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ํ•„์š”ํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋‹ค์šด๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
  2. terraform plan: ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ฏธ๋ฆฌ ํ™•์ธํ•˜์—ฌ ์–ด๋–ค ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ์„ฑ, ์ˆ˜์ •, ์‚ญ์ œ๋ ์ง€ ๊ณ„ํš์„ ์„ธ์›๋‹ˆ๋‹ค.
  3. terraform apply: Terraform ์ฝ”๋“œ๋ฅผ ์‹ค์ œ๋กœ ์ ์šฉํ•˜์—ฌ ์ธํ”„๋ผ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
  4. terraform destroy: Terraform์œผ๋กœ ์ƒ์„ฑ๋œ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

Terraform ๋‹จ์ผ ํŒŒ์ผ ๋ฐฐํฌ, ๋ณ€์ˆ˜ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•œ ๋ฐฐํฌ

GCP์˜ ๊ธฐํ•œ์ด ์‚ฌ๋ผ์ ธ์„œ ์ œ๊ฐ€ ์ ‘์†์ด ์•ˆ๋˜์–ด์„œโ€ฆ ์—ฌ๊ธฐ๋ฅผ ๋‹ค์‹œ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค..