# Heroku에서 Docker 배포

- Author: @baealex
- Published: 2021-11-01
- Updated: 2021-11-01
- Source: http://blex.me/@baealex/heroku%EB%A1%9C-docker-%EB%B0%B0%ED%8F%AC-1
- Tags: 도커, 배포

---

개발을 진행했으나 배포하지 않았던 토이 프로젝트를 Heroku를 통해 배포하고자 하였다. Heroku를 선택한 이유는 `docker-compose` 와 유사한 형태로 도커 컨테이너의 배포가 가능하다는 점이 매력적이었다. 무료 플랜을 제공하고 있으나 서비스 용도로는 부적합해 보이며 데모 사이트 정도로 쓰기에 괜찮을 듯 하다.

<center>

<br>

![](https://static.blex.me/images/content/2021/11/1//2021_11_1_21_1M0JdE63z29P8AIGcF5Y.jpg)

<br>

</center>

#### Heroku CLI 설치

우선 `Heroku CLI` 설치가 필요하다. 필자와 같이 데비안 계열의 리눅스를 사용한다면 아래와 같이 설치할 수 있다. 그 외 운영체제는 https://devcenter.heroku.com/articles/heroku-cli 를 참고하여 설치하자.

```bash
curl https://cli-assets.heroku.com/install-ubuntu.sh | sh
```

#### 사전 설정

CLI를 통해 로그인을 진행하자.

```bash
heroku login
```

Heroku에 만들어 둔 앱이 없다면 아래와 같이 `create` 명령어를 통해서 즉시 생성할 수 있다. `create` 뒤에 `<APP_NAME>`은 생략이 가능하며 생략시 무작위로 이름이 만들어진다.

```bash
heroku create <APP_NAME>
```

Heroku에 이미 만들어둔 프로젝트가 있다면 다음과 같이 연결할 수 있다.

```bash
heroku git:remote <APP_NAME>
```

Docker 컨테이너 형태로 배포하고자 한다면 아래 명령어를 입력하여 스택 유형을 바꿔주어야 한다. 아래 명령어를 실행하지 않을 경우 오류가 발생한다.

```bash
heroku stack:set container
```

#### heroku.yml

프로젝트 경로에 `heroku.yml`을 생성하자.

```yml
build:
  docker:
    web: server/Dockerfile
```

대략 위와 같다. 위의 경우는 Dockerfile이 `heroku.yml`과 같은 디렉터리에 있지 않으므로 서브 디렉터리를 명시해 주었다. 같은 경로에 있다면

```yml
build:
  docker:
    web: Dockerfile
```

위와같이 작성할 수 있다.

```yml
build:
  docker:
    web: Dockerfile
run:
  web: bundle exec puma -C config/puma.rb
```

`run` 속성에서 컨테이너 이름에 명령어를 명시하면 명시된 명령어로 컨테이너가 실행되고 `run` 속성이 존재하지 않는 경우 기본적으로 `Dockerfile`에 작성된 명령으로 실행한다.

```bash
git add heroku.yml
git commit -m "Add heroku.yml"
git push
```

```bash
git push heroku master
```

`Git`과 `Heroku`에 각각 푸시를 해주었다. 배포 끝!

#### Port 설정

우선 필자가 배포하는 동안 문제를 겪었던 부분은 포트와 관련된 부분이었다. `Heroku`의 환경변수로 지정해준 포트에서 장시간 서비스가 실행되지 않을 경우 Crash로 처리된다. 따라서 우리의 서비스를 환경변수에서 제공해주는 포트로 실행해야 한다.

###### in Python

```py
import os

from flask import Flask

application = Flask(__name__)

if __name__ == '__main__':
    application.run(host='0.0.0.0', port=int(os.environ.get("PORT", 5000)))
```

###### in Node

```js
import express from 'express'

const port = process.env.PORT || 3000

const app = express()
    .listen(port, () => console.log(`listen on :${port}`))
```
