docker-compose로 개발환경을 구축하기 위해 아래와 같이 docker-compose.dev.yml 파일을 작성했었다.

version: "2"

services:
  db:
    image: mysql:5.7.34
    container_name: dorandoran_db

    ports:
      - "7001:3306"
    environment:
      - MYSQL_DATABASE=dorandoran_dev_db
      - MYSQL_USER=devuser
      - MYSQL_PASSWORD=password
      - MYSQL_ROOT_PASSWORD=password
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  web:
    build:
      context: .
      dockerfile: ./compose/develop/Dockerfile-dev
    volumes:
      - ./:/app/
    command:
      - bash
      - -c
      - |
        python dorandoran/manage.py migrate
        python dorandoran/manage.py runserver 0.0.0.0:8000
    container_name: dorandoran_web
    env_file:
      - dev.env
    depends_on:
      db:
        condition: service_healthy
    restart: always
    ports:
      - "8000:8000"

분명 webdb에 의존하고 있음을 명시하고 healthcheck까지 붙여줬는데 왜 안되는지 이해가 안됐다.

문제는 dev.env 파일에 있었다.

DJANGO_DB_HOST=db
DJANGO_DB_PORT=7001  # 이곳
DJANGO_DB_NAME=dorandoran_dev_db
DJANGO_DB_USERNAME=root
DJANGO_DB_PASSWORD=password

web 컨테이너가 db 컨테이너에 접근 할 때의 포트를 외부 포트(7001)로 지정해 줬던 것이다.
내부 포트인 3306으로 바꾸니 제대로 동작하였다.

DJANGO_DB_HOST=db
DJANGO_DB_PORT=3306  # 잘 된다!
DJANGO_DB_NAME=dorandoran_dev_db
DJANGO_DB_USERNAME=root
DJANGO_DB_PASSWORD=password

오류 내용


윈도우 환경에서 실행할 때는 잘 돌아갔는데 Docker에 올려 리눅스 환경에서 실행할 때 위와 같은 에러가 발생했다.

우선 해결 방법은 maxsize를 지정해 주면 된다.
ex) @lru_cache(maxsize=128)

왜 이러지?

찾아봤는데 윈도우와 리눅스 환경의 차이는 아니고 파이썬 버전에 차이가 있었다.

Python 3.7
Python 3.8

Python 3.8 의 517번째줄 주석을 보면 "user_fuction 이 maxsize 인수로 직접적으로 전달되었다." 라는 말이 있다.

Python 3.8에서는 데코레이터의 wrap function이 maxsize로 전달되어 버렸을 때의 데이터 처리 과정이 있지만 Python 3.7에는 존재하지 않는다.

그렇기 때문에 maxsize를 지정해 주지 않으면 wrap function이 maxsize로 전달되어 버려 예외가 일어나는 것이다.

프로젝트를 진행하면서 변경사항이 없어도 계속 makemigrations가 가능해 migration 파일이 계속 생성되는 오류가 발생했다.

 

이유를 생각해 보니 role 필드의 choices 옵션이 떠올랐다.

ROLE_CHOICES = {  # <- set!
        (STUDENT, "student"),
        (TEACHER, "teacher"),
        (ADMIN, "admin"),
}

role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES)

위와 같이 ROLE_CHOICES를 set 자료형으로 만들었는데, 파이썬의 set 자료형은 순서가 존재하지 않는다.

migrations/0001_initial.py

그래서 migration 파일을 보면 status의 choices 옵션이 makemigrations 할때마다 이것만 바뀐 파일이 생성되는 것을 알 수 있다.

 

결론은 set 자료형이 아닌 tuple 혹은 list 자료형을 사용해주면 된다

ROLE_CHOICES = (  # <- tuple!
        (STUDENT, "student"),
        (TEACHER, "teacher"),
        (ADMIN, "admin"),
)

role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES)

이동욱 저자님의 "스프링 부트와 AWS로 혼자 구현하는 웹서비스" 책을 보면서 travis ci로 자동 배포를 테스트 해보는 도중 변경사항이 적용이 되지 않았다.

travis ci 모니터링 텝에서도 오류가 잡히지 않아 무엇이 문제인지 직접 찾아야 했다.

오류 하나에 수많은 배포의 흔적... (테스트는 잘 통과함)

그래서 직접 EC2 인스턴스에 접근해서 ps 명령어를 사용해 프로세스를 확인해 봤다.

cmd 이름이 java네...?

위와 같이 나오는 것을 보고 뭔가 이상한거 같아서 deploy.sh 파일을 확인해 봤다.

이름이 jar인 프로세스를 찾아서 지우는 거네..

프로세스 이름은 java인데 jar인 프로세스를 검색해서 지우니까 기존에 돌아가던 프로세스가 중지되지 않아서 생긴 문제였다.

프로세스가 중지가 되지 않으니까 포트도 충졸한 것 같다. (nohup.out 로그를 보면 자세히 확인 할 수 있다.)

 

jar를 java로 바꿔서 해결해주자!

 

해결!

 

EC2 인스턴스에서 Spring boot jar을 실행하자 There is insufficient memory for the Java Runtime Environment to continue. 라는 에러가 검출되었다.

 

충분한 메모리가 확보되지 않았다는 것인데, 순간 떠올린 방법은 두가지였다

1. EC2의 메모리를 확장시킨다 (t3.micro 보다 큰)

2. -Xmx 와 같은 옵션으로 메모리를 직접 할당해준다.

 

1번은 돈이 나가기 때문에 포기했고, 2번을 하려고 했을때, 이전에 실행해둔 프로세스가 생각이 나서 출력을 해보았다.

> ps aux

알고보니 이전에 실행해둔 프로세스 때문에 메모리가 부족한 것이었다. 그래서 ec2 인스턴스를 재부팅 해서 해결했다.

클라우드 기능반 과제 중에서 Bastion Host에 접속해서 private subnet에 접속하는 과제가 있었다. 그런데 클라이언트에서 바스천 호스트로 퍼블릭 키 파일(.pem)를 전달할 때 오류가 발견되었다.

root@0.0.0.0 : ~# scp ./hanbin.pem ec2-user@1.2.3.4:/home/
Permission denied (publickey,gssapi-keyex,gssapi-with-mic) 

 

해결 과정 #1

검색을 해보니

https://serverfault.com/questions/598058/ssh-permission-denied-publickey-gssapi-with-mic-password

 

SSH: Permission denied (publickey,gssapi-with-mic,password)

==================================================================== UPDATE: It turned out the configuration of sshd on host2 wont allow password login. Thanks to people answered this. =========...

serverfault.com

파일 권한을 변경해주라고 하는데 내 경우에는 해결이 되지 않았다.

 

해결 과정 #2

root@0.0.0.0 : ~# scp -i hanbin.pem ./hanbin.pem ec2-user@1.2.3.4:/home/ec2-user/
Permission denied (publickey,gssapi-keyex,gssapi-with-mic) 

혹시나 해서 identify file(.pem)도 명시해주고 /home/ 경로가 아닌 유저 경로 /home/ec2-user/로 지정해 줬더니 됐다.

 

내 생각에는 ssh-add 설정을 잘못 해주어서 RSA Host key를 읽지 못했던 것 같다.

문제가 해결된 이유는

1. 직접 identify file을 명시했음

 

2. <유저 이름>@<ip 주소>:<경로> 에서 유저(ec2-user)의 권한에 맞는 경로(/home/ec2-user)를 지정해 주니 됐음

 

문제점

이동욱님의 "스프링 부트와 AWS로 혼자 구현하는 웹 서비스"를 보고 따라하다가 Gradle verification test에서 에러가 났다.

해결방법

/gradle/wrapper/gradle-wrapper.properties 에서 Gradle의 버전을 4.10.2로 맞춰주면 된다.

 

버전 문제라는 것도 모르고 3시간동안 뻘짓을 했다...

문제점

노트북에서 데스크탑으로 개발 환경을 옮기고 테스트 코드를 실행하는데 "cannot find symbol" 에러가 나타났다.

해결 과정 #1

롬북이 안깔려 있어 getter가 생성되지 않은 에러라고 생각해서 롬북이 깔려 있는 확인해 봤다.

그런데 깔려있네??? 이건 아닌가보다

해결 방법

Enable annotation processing 을 체크해주면 컴파일 시간동안 annotation을 처리하도록 구성할 수 있다. 누르고 다시 실행해 주자...

잘된다!!

+ Recent posts