written by yechoi

[gunicorn] 서비스 등록 - 111: Connection Refused, 13: Permission Failed 해결 본문

Born 2 Code/Web

[gunicorn] 서비스 등록 - 111: Connection Refused, 13: Permission Failed 해결

yechoi 2021. 3. 14. 22:40
반응형

gunicorn을 사용하는 데는 두가지 방식이 있다.

하나는 포트를 이용해 서버를 띄우는 것이다. gunicorn --bind 0:8000 config.wsgi:application 와 같은 커맨드가 그러한 역할을 한다.

두번째는 소켓을 사용하는 것이다. unix 계열 시스템에선 포트로 서비스 하는 것보다 유니스 소켓을 사용하는 게 빠르고 효율적이라고 한다. gunicorn --bind unix:/tmp/gunicorn.sock config.wsgi:application와 같은 커맨드로 소켓을 사용할 수 있다.

나는 소켓을 사용하는 방식을 택했다. 자동적으로 gunicorn을 실행하기 위해선 앞선 명령어를 매번 쓰는 것보단, gunicorn을 서비스로 등록하는 게 좋다.

 

gunicorn 서비스로 등록하기

서비스 파일 만들기

서비스에 등록하기 위해선 아래와 같은 경로에 .service 파일을 만든다. (확장자 앞의 파일 이름은 사이트 이름이라든지 프로젝트 이름으로 해도 되지만, 나는 단순하게 gunicorn.service로 이름 지어줬다.)

 

cat /etc/systemd/system/gunicorn.service

[Unit] 
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=humansof42
Group=www-data
WorkingDirectory=/home/humansof42/h42
ExecStart=/home/humansof42/.local/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          config.wsgi:application
Environment=H42_SECRET_KEY=abcdedf

위의 파일은 gunicorn.socket 파일을 참조해 소켓을 만든다. .socket 파일은 다음과 같이 만든다. ListenStream은 듣고 있는 소켓의 위치를 지정한다. (gunicorn.socket도 마찬가지로 이름을 mysite.socket 등등으로 지어도 괜찮다. 앞선 .socket 파일에서 잘만 참조하고 있다면.)

 

cat /etc/systemd/system/gunicorn.socket

[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target

 

서비스 실행하고 등록하기

sudo systemctl start gunicorn.service

 

서비스 재실행하기

sudo systemctl restart gunicorn
sudo systemctl daemon-reload
sudo systemctl restart gunicorn.socket gunicorn.service

 

 

111: Connection Refused

나는 이과정에서 여러 에러를 겪었는데, 111:Connection Refused 에러의 경우 gunicorn.service 파일에서 필요한 변수들을 제대로 세팅해주지 않았기 때문이다. 남들의 gunicorn.service 파일을 복붙해줬던 것이 원인. 구체적으로 아래의 두가지 경우가 문제였다.

  • User 이름을 root, ubuntu 등 내 User가 아닌 명칭을 사용했던 것
  • django에서 필요로 하는 SECRET_KEY 환경변수를 세팅해주지 않은 것

참고로 환경변수를 세팅할 때는 Environment=H42_SECRET_KEY=abcdedf 이런식으로 하드 코딩할 수도 있지만, 원하는 위치에 환경변수용 파일을 따로 만들어서 인클루드 해줄 수도 있다. 다음과 같은 식으로 설정하면, 비공개해야 할 환경변수를 공개해버리는 일을 막을 수 있다.

 

cat /home/humansof42/h42/config/h42.env

H42_SECRET_KEY=abcdef

 

cat /etc/systemd/system/gunicorn.service

[Unit] 
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=humansof42
Group=www-data
WorkingDirectory=/home/humansof42/h42
ExecStart=/home/humansof42/.local/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          config.wsgi:application
EnvironmentFile=/home/humansof42/h42/config/h42.env

 

 

13: Permission Denied

앞선 문제를 해결하고 마주한 에러는 13: Permission Denied. 이건 nginx에 소켓의 위치를 제대로 지정해주지 않았기 때문이다.

server {
    listen 80;
    server_name 34.64.112.133;
    charset utf-8;
    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /root/humansof42/h42;
    }
    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

proxy_pass에 우리가 만들어놓은 소켓을 넣어둬야 한다. 이전엔 proxy_pass http://unix:/etc/systemd/system/gunicorn.socket; 으로 엉뚱하게 소켓 대신 소켓 설정파일을 넣어뒀었다.

참고: https://wikidocs.net/76904

 

위키독스

온라인 책을 제작 공유하는 플랫폼 서비스

wikidocs.net

 

반응형