lambda, docker 배포 및 환경변수 설정하기

송윤주·2024년 2월 10일
0

클라우드

목록 보기
2/8

결론부터 알고 싶으신 분들은 'AWS Lambda 환경 변수 기능 활용하기'으로 바로 넘어가시면 됩니다.

민감한 정보를 숨기기 위해서?

프로젝트를 진행하다 보면 api key 값이라던가... 아이디 패스워드 값이라던가.. 중요한 정보를 관리해야할 필요가 있다. 이전 프로젝트에서는 그런 값들이 필요가 없어서 그냥 이미지화하고 ecr에 업로드해서 lambda함수를 생성했었는데 이번에는 elastic search의 클라우드 id나 인덱스 명, api key값 등 중요한 정보를 숨겨야 했다. 그렇다면 이 값들을 어떻게 관리할 수 있을까? 총 두가지 방법으로 나눌 수 있다.

Docker 컨테이너 및 AWS Lambda 환경에서 환경변수 설정하기

1. 'docker-compose.yml 파일을 사용하는 방법

Docker 환경에서는 위 파일을 통해 여러 컨테이너의 설정을 정의하고 각 컨테이너에 필요한 환경변수를 설정할 수 있다. 이 방법은 로컬 개발환경이나 Docker를 사용하는 다른 환경에서 특히 유형하다.

version: '3'
services:
  myservice:
    image: myimage
    environment:
      ELASTIC_CLOUD_ID: "my_cloud_id"
      ELASTIC_API_KEY: "my_api_key"
    env_file:
      - .env

위 코드처럼 yml 파일을 작성할 수 있는데 여기서 environment는 직접 환경 변수를 명시적으로 설정할 수 있게하고 env_file 섹션은 .env 파일로부터 환경변수를 로드한다.

2. AWS CLI를 사용하는 방법

AWS Lambda에서는 AWS CLI를 사용해 함수의 환경 변수를 설정하거나 업데이트를 할 수 있다. 이 방법은 AWS 환경에서 Lambda함수를 배포하고 관리할 대 사용된다.

aws lambda update-function-configuration --function-name my-function \
--environment "Variables={ELASTIC_CLOUD_ID=my_cloud_id,ELASTIC_API_KEY=my_api_key}"

이 명령은 my-function이라는 이름의 Lambda 함수에 ELASTIC_CLOUD_ID와 ELASTIC_API_KEY라는 환경 변수를 설정한다.

정리

  • Docker 환경에서는 docker-compose.yml이나 Dockerfile의 ENV 지시어를 사용하여 환경 변수를 설정한다. 이는 개발, 테스트 등 Docker를 사용하는 환경에 적합하다.
  • AWS Lambda 환경에서는 AWS CLI, AWS Management Console, 또는 AWS SDKs를 통해 환경 변수를 설정한다. 이는 클라우드 환경에서 서버리스 애플리케이션을 운영할 때 필요하다.

보안적으로 좋은 선택?

도커 컨테이너에서 환경 변수 사용 시 고려할 보안 사항

  1. Docker 이미지 내 환경 변수 포함 시키지 않기docker-compose.yml 파일이나 Dockerfile에 직접 민감한 정보를 포함시키지 않는 것이 중요하다. 이런 파일들이 Git 같은 버전 관리 시스템에 포함될 경우, 민감한 정보가 노출될 위험이 있기 때문.
  2. 환경 변수 파일(.env)을 사용할 경우: Docker Compose를 사용하고 .env 파일에서 환경 변수를 로드하는 경우, 이 파일을 이미지에 포함시키지 않도록 주의해야 한다. 또한, .env 파일을 Git이나 다른 버전 관리 시스템에서 제외시켜야 한다(.gitignore에 추가).
  3. AWS Lambda와 Docker 사용 시: AWS Lambda에서 Docker 컨테이너 이미지를 사용할 경우, AWS Lambda의 환경 변수 관리 기능을 활용하여 민감한 정보를 안전하게 관리할 수 있다. Lambda 함수 생성 시 또는 업데이트 시 AWS Management Console, AWS CLI, 또는 AWS SDK를 사용하여 환경 변수를 설정할 수 있으며, 이러한 환경 변수는 AWS에서 암호화하여 안전하게 관리된다.

결론 : 이미지화할 때는 yml 파일이던 .env 파일이던 노출될 가능성이 존재하니 다른 방법을 고려해라.

Docker 이미지에 환경 변수를 포함하려 한다면?

Docker 이미지에 환경 변수를 포함하려 할 때, docker-compose.yml 파일에 환경 변수를 직접 작성하는 것이 보안적으로 우려될 수 있다. 특히, 민감한 정보를 다루는 경우 더욱 그렇다고 한다. (아직 실무를 접하지 않아서 모르지만...) 하지만 Docker 이미지 빌드 과정에서 환경 변수를 안전하게 포함하는 방법은 여러 가지가 존재한다고 한다. 그 방법은 아래와 같다.

1. Dockerfile의 ARG 지시어 사용

Dockerfile에서 ARG 지시어를 사용하여 빌드 시간 변수를 정의할 수 있습니다. 이 방법은 이미지를 빌드할 때만 변수를 사용할 수 있으며, 빌드가 완료된 후 이미지에 변수를 남기지 않습니다. 민감한 정보를 빌드 과정에서만 사용해야 할 때 유용하다.

# Dockerfile
ARG ELASTIC_CLOUD_ID
ARG ELASTIC_API_KEY

# ARG로 받은 값을 환경 변수로 설정
ENV ELASTIC_CLOUD_ID=${ELASTIC_CLOUD_ID}
ENV ELASTIC_API_KEY=${ELASTIC_API_KEY}

Docker 이미지를 빌드할 때는 --build-arg 옵션을 사용하여 값을 전달한다:

docker build --build-arg ELASTIC_CLOUD_ID=your_cloud_id --build-arg ELASTIC_API_KEY=your_api_key -t your_image_name .

하지만 이 방법은 환경변수가 많을 수록 cli 코드 관리가 힘들다는 단점이 있는 것 같다.

2. 런타임에 환경 변수 전달

Docker 이미지를 실행할 때 docker run 명령어의 -e 또는 --env 옵션을 사용하여 환경 변수를 컨테이너에 전달할 수 있다. 이 방법은 이미지에 민감한 정보를 포함시키지 않고, 컨테이너 실행 시 필요한 환경 변수를 제공할 수 있다.

docker run -e ELASTIC_CLOUD_ID=your_cloud_id -e ELASTIC_API_KEY=your_api_key your_image_name

3. 환경 변수 파일 사용

환경 변수를 포함한 파일을 작성하고, 이 파일을 docker run 명령어의 --env-file 옵션을 통해 컨테이너에 전달할 수 있다. 이 파일은 런타임에만 사용되며, 이미지에는 포함되지 않는다.

# .env 파일
ELASTIC_CLOUD_ID=your_cloud_id
ELASTIC_API_KEY=your_api_key
docker run --env-file .env your_image_name

2번과 3번 방법은 Docker 이미지를 실행할 때 환경변수를 전달하는 방법이라 이미지를 빌드할 때는 사용할 수 없고 런타임에 컨테이너 환경에 환경 변수를 주입하는 데 사용되어 말그대로 테스트 용도이다.

결론

위에 내용에서 알 수 있듯이 도커 이미지 빌드에서 환경변수를 설정하는 것은 말그대로 !!테스트!! 즉 로컬에서 돌려볼 때 적합한 작업인 것 같고 결국 배포할 때 환경변수를 관리하기 위해서는 AWS 라는 기업의 서비스를 이용하는 것이 좋다.

이것외에도 멀티-스테이지 빌드를 사용할 수 있다고 하는데 나중에 알아보자.


AWS Lambda 환경 변수 기능 활용하기

AWS Lambda에서 Docker 컨테이너 이미지를 사용할 때, 민감한 정보를 포함하지 않고 환경 변수를 안전하게 관리하려면, AWS Lambda의 환경 변수 기능을 활용해야 한다. 이 방법을 사용하면 Docker 이미지에 민감한 정보를 포함시킬 필요 없이, Lambda 함수 실행 시 필요한 환경 변수를 제공할 수 있다.

코드에서 환경변수 접근하기

람다 함수 내부에서는 아래와 같은 방식으로 접근할 수 있다.

import os

ELASTIC_CLOUD_ID = os.getenv('ELASTIC_CLOUD_ID')
ELASTIC_API_KEY = os.getenv('ELASTIC_API_KEY')
# 환경 변수 사용...

Lambda 함수가 실행될 때 AWS는 설정된 환경 변수를 Lambda 실행 환경에 주입하므로, 애플리케이션 코드에서 필요한 구성 정보를 안전하게 사용할 수 있다.

Docker 이미지 준비

람다 함수 코드, 관련된 함수 코드 파일, 도커파일 등등 필요한 것들을 이미지로 말기위한 준비를 해야된다. 뭐 이것은 검색하면 다 나오기 때문에 생략한다. 그치만 나의 탐구욕은 멈출 수 없다. 모든 것은 이해했으나 왜 작업 디렉토리가 WORKDIR /var/task 여기일까?

작업 디렉토리의 위치

AWS Lambda에서 Docker 컨테이너 이미지를 사용할 때, /var/task 디렉토리는 Lambda 실행 환경에서 코드와 라이브러리 파일들을 찾는 기본 위치이다.
AWS Lambda의 컨테이너 이미지 지원은 이 위치에서 함수 코드를 실행하기를 예상하고 있고 WORKDIR/var/task로 설정하는 것은 Lambda 함수가 올바르게 실행되도록 하는 데 중요하다고 한다.

Lambda 실행 환경은 /var/task 디렉토리를 함수 코드와 그 의존성이 있는 '작업 디렉토리'로 사용한다. 이 경로를 기준으로 Python 모듈을 찾고, 핸들러 함수를 지정할 때의 참조 경로 역시 이 디렉토리를 기반으로 한다.

예를 들어, CMD ["query.lambda_handler"]에서 query/var/task 디렉토리 내의 query.py 파일을 가리킨다.

WORKDIR을 다른 위치로 설정하게 되면 Lambda 함수가 정상적으로 실행되지 않거나, 코드나 라이브러리를 찾지 못하는 문제가 발생할 수 있다. 따라서, AWS Lambda에서 Docker 컨테이너를 사용할 때는 WORKDIR/var/task로 설정하는 것이 권장되며, 이는 Lambda의 기본 실행 환경과 일치하도록 설정된 것이다.

WORKDIR의 설정은 사용하는 프로그래밍 언어에 직접적으로 의존적이지 않다. 대신, 애플리케이션의 구조, 사용하는 베이스 이미지의 관례, 그리고 특정 실행 환경(AWS Lambda와 같은)의 요구사항에 따라 결정된다.

자세한 건 역시 공식문서 가 최고지요?!

Docker 이미지 빌드 및 ECR에 업로드

  1. 이미지 빌드:

    docker build -t lambda-function-image .
    
  2. Amazon ECR 리포지토리 생성(미리 생성하지 않았다면):

    aws ecr create-repository --repository-name lambda-function-repo
    

    이건 gui 상에서도 가능하다! 굳이 cli 사용하지 않아도 됨.
    근데 cli 상에서 aws 명령어를 사용하려면 aws configure 설정 해야된다.

    📍 configure 설정 시 등록하는 id와 key 값은 aws id, passwd가 아니다. aws iam -> 사용자 -> 보안 자격증명 -> 액세스 키로 발급해야 한다. (사실 내가 했던 실수지롱)
    📍 ECR 레포 생성시 프라이빗으로 설정해야지 lambda와 연결 가능하다.

  3. Docker 로그인:

    aws ecr get-login-password --region your-region | docker login --username AWS --password-stdin your-account-id.dkr.ecr.your-region.amazonaws.com
    
  4. 이미지 태그 지정:

    docker tag <source_image>:<tag> <repository_url>:<tag>
    
  • <source_image>:<tag>는 로컬에서 사용하고 있는 이미지의 이름과 태그이다. 예를 들어, lambda-function-image:latest에서 lambda-function-image는 이미지 이름이고, latest는 이미지의 태그이다.
  • <repository_url>는 이미지가 저장될 ECR 리포지토리의 URL이다. 여기에는 AWS 계정 ID, ECR 서비스의 도메인, 리전, 그리고 리포지토리 이름이 포함된다.
    - 예: your-account-id.dkr.ecr.your-region.amazonaws.com/lambda-function-repo.
  • 마지막 <tag>는 리포지토리에 푸시될 때 사용될 이미지의 태그이다. 이 태그를 통해 동일한 이미지의 다양한 버전을 구분할 수 있다. 예를 들어, latest, v1, v2 등과 같이 사용될 수 있다.
  1. ECR에 이미지 푸시:

    docker push your-account-id.dkr.ecr.your-region.amazonaws.com/lambda-function-repo:latest

    📌 주의! 레포이름과 url 주소 잘 봐라... 안그러면 EOF 에러를 만나게 될 수도... (는 내얘기)

위 과정을 통해 완료해보자!

AWS Management Console

Lambda 함수 생성 또는 선택

람다 함수를 만들 때 만든 ecr 레포를 참고해서 생성한다.

함수 구성

함수 대시보드에서 "구성" 탭을 선택한다.
좌측 사이드바에서 "환경 변수"를 선택한다.
그다음 편집~~

환경 변수 추가

여기서 키(key)와 값(value)을 입력하면 된다.

AWS CLI 를 사용해서 환경변수 설정

콘솔에서 말고 cli를 사용해 설정하는 방법도 있다.

aws lambda update-function-configuration --function-name my-function \
--environment "Variables={ELASTIC_CLOUD_ID=my_cloud_id,ELASTIC_API_KEY=my_api_key,ELASTIC_INDEX=my_index,ELASTIC_MODEL=my_model}"

여기서 my-function은 Lambda 함수의 이름이며, --environment 옵션 뒤에는 환경 변수들의 키-값 쌍을 JSON 형식으로 제공한다.

반환 값 확인

포스트맨으로 확인했을 때 결과값 잘 나오는 것을 확인할 수 있었다!

사실 여기서 무슨 Error: fork/exec /lambda-entrypoint.sh: exec format error Runtime.InvalidEntrypoint 에러가 났었는데 동네방네 팔짝뛰며 찾아본 결과 도커파일에서 FROM 즉 베이스 이미지를 지정하는 지시어의 코드가 어긋나있었다.

장장 5시간을 공들이며 작성한... 블로그글...
개발만 했을 때는 몰랐지만 남들이 보기 쉽게끔 정제하며 작성하는 게 은근 많이 어렵고 시간이 많이 드는 구나... 를 체감했다. 그러나 작성하면서 나도 개념 정리 + 회고를 진행할 수 있어서 좋다!

사실 이게 apigateway를 사용해야 되는데 일단 테스트 코드가 잘 되는지 확인하기 위해 퍼블릭 url로 통신했다. 그래서 다음 주제는... lambda와 api gateway를 연결하는 것에 대해 다루겠다.

안뇽~~~ 👋👋👋

profile
모두가 정보를 습득할 수 있도록 냠냠쩝쩝 먹어보는 공간

0개의 댓글

관련 채용 정보