> For the complete documentation index, see [llms.txt](https://docs.edgegap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.edgegap.com/ko/docs/tools-and-integrations/docker.md).

# Docker 및 컨테이너

Edgegap이 게임 서버를 컨테이너에서 실행하는 이유와 첫 서버 이미지를 빌드하기 전에 Docker를 어떻게 설정하는지 설명합니다.

{% columns %}
{% column width="25%" %}

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-e6111f686dccc8bebc29f2f10fe2ce093f9c2b9c%2Fdocker.png?alt=media" alt="" width="100"><figcaption></figcaption></figure>
{% endcolumn %}

{% column width="75%" %}
Docker는 애플리케이션을 개발, 배포, 실행하기 위한 오픈 플랫폼입니다. Docker를 사용하면 애플리케이션을 인프라와 분리할 수 있어 소프트웨어를 빠르게 제공할 수 있습니다.
{% endcolumn %}
{% endcolumns %}

## 왜 Docker를 사용해야 하나요?

개발자 팀과 함께 작업하면 코드를 공유해야 합니다. 문제가 발생했을 때 듣고 싶은 마지막 말은 “내 환경에서는 잘 돼”일 것입니다. 게임 서버는 전 세계 수천 대의 서버 머신에서 안정적으로 실행되어야 합니다.

서버를 안정적으로 만들기 위해 Docker를 사용합니다 - 운영 체제 수준까지 서버 코드의 모든 종속성이 어디서 어떻게 서버가 시작되든 항상 정확히 동일하도록 보장하는 가상화 소프트웨어입니다.

{% hint style="info" %}
시청을 권장합니다 ["로컬에 설치하지 마세요" (비디오)](https://www.youtube.com/watch?v=J0NuOlA2xDc\&ab_channel=Coderized). **Docker를 사용할 때 Dockerhub를 사용할 필요는 없습니다**Docker ≠ Dockerhub. Docker를 프로그래밍 엔진으로 보고 Dockerhub를 앱 스토어로 생각하세요.
{% endhint %}

## 컨테이너

하나의 **컨테이너는 코드를 패키징하는 소프트웨어의 표준 단위이며** 모든 종속성을 함께 담아 애플리케이션이 한 컴퓨팅 환경에서 다른 환경으로 빠르고 안정적으로 실행되게 합니다. 컨테이너는 소프트웨어를 실행 환경과 분리하고, 예를 들어 개발과 스테이징 간의 차이에도 불구하고 일관되게 동작하도록 보장합니다.

\
패키징된 Docker 이미지를 실행하면, 그것들은 다음과 같습니다:

* **컨테이너** Docker Desktop 또는 Docker Engine에서 실행 중인 경우(보통 로컬에서),
* &#x20;[배포](/ko/learn/orchestration/deployments.md) Edgegap에서 실행 중인 경우(Edge Cloud 및 Private Fleet 모두).

컨테이너는 Linux(또는 Docker Desktop)에서 네이티브로 실행되며 호스트 머신의 커널을 다른 컨테이너와 공유합니다. 별도의 프로세스로 실행되며, 추가 실행 파일보다 더 많은 메모리를 사용하지 않아 가볍습니다.

<figure><img src="https://1562312210-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-f150d345ddba740a7babd5338aca3f557cc1886c%2Fcontainer-architecture.png?alt=media" alt=""><figcaption></figcaption></figure>

## **직접 해보기**

Docker를 사용해 로컬에서 Docker 이미지를 빌드하거나 실행하려면 Docker를 설치해야 합니다:

<details>

<summary><a href="https://www.docker.com/products/docker-desktop/">Docker Desktop(또는 Docker CLI) 설치</a></summary>

* [공식 소스에서 Docker Desktop을 설치하세요](https://www.docker.com/products/docker-desktop/) (계정이 필요하지 않습니다).
* 설치를 완료한 후 컴퓨터를 다시 시작하세요.

</details>

설치가 완료되면 원하는 터미널을 열고 테스트 이미지를 실행해 볼 수 있습니다.

```sh
docker run -d -p 80:80 --name speedtest edgegap/speedtest-edge
```

그러면 다음 단계가 자동으로 수행됩니다:

1. Edgegap Repository에서 speedtest 이미지를 다운로드합니다(처음 한 번만).
2. 이 이미지를 사용해 머신에 새 컨테이너를 생성하고 시작합니다.
3. "speedtest"라는 이름을 지정합니다( `--name` 매개변수를 사용).
4. 다음을 노출하여 [앱 및 버전](/ko/learn/orchestration/application-and-versions.md#port-mapping) 머신의 포트를 연결할 `80`  컨테이너의 포트 `80` 에 연결할 수 있게 하여, 머신에서 컨테이너에 접근할 수 있도록 합니다.

✅ 열기 [http://localhost:80](http://localhost/) 를 선호하는 브라우저에서 열어 컨테이너가 정상적으로 시작되었는지 확인하세요.

컨테이너가 실행되면 기본적인 상호작용을 할 수 있습니다 - 재시작, 중지, 모니터링.&#x20;

먼저, 선호하는 터미널을 사용해 Docker 엔진에서 무엇이 실행 중인지 확인해 봅시다.

```sh
docker ps
```

그러면 실행 중인 컨테이너에 대한 정보가 출력됩니다. 예를 들면:

```
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                NAMES
dbf4d3734111        edgegap/speedtest-edge   "docker-php-entrypoi…"   29분 전           실행 중 29분         0.0.0.0:80->80/tcp   speedtest
```

실행 중인 컨테이너는 원하는 만큼 둘 수 있습니다.

컨테이너에 대한 더 많은 정보를 확인해 봅시다:

```sh
docker container inspect speedtest
```

머신과 컨테이너 사이에서 공유되는 네트워크도 살펴볼 수 있습니다.

```sh
docker network ls
```

그러면 머신의 Docker 엔진에서 실행 중인 네트워크에 대한 정보가 출력됩니다.

```
NETWORK ID          NAME                DRIVER              SCOPE
67b24038b9ca        bridge              bridge              local
6f7fe43a489d        host                host                local
3d80cdb86a7e        none                null                local
```

개별 네트워크도 자세히 확인할 수 있습니다:

```sh
docker network inspect 67b24038b9ca
# 678b24038b9ca는 컨테이너에 연결된 네트워크입니다
```

컨테이너 테스트가 끝나면 컨테이너가 사용하던 리소스(CPU 및 RAM)를 되찾을 수 있도록 반드시 중지하세요:

```sh
docker container stop speedtest
```

## SSH 터널

서버 문제를 깊이 있게 진단하려면 이미지에서 SSH 서비스를 노출하고, 원격 호스트나 VM과 마찬가지로 컨테이너나 배포에 연결할 수 있습니다.

{% hint style="danger" %}
**프로덕션 배포에서는 SSH 서비스를 절대 노출하지 마세요** - 심각한 보안 문제입니다.
{% endhint %}

### 로컬 테스트

Dockerfile에 몇 가지 수정을 해야 합니다. OpenSSH 서비스를 설치하고, 비밀번호가 있는 사용자를 생성하고, 서비스를 활성화합시다.

{% hint style="success" %}
**Dockerfile 명령의 순서는 중요합니다!** [Docker는 빌드 속도를 높이기 위해 레이어를 캐시합니다.](https://docs.docker.com/build/cache/) 다음과 같은 캐시되지 않는 레이어는 `RUN` 및 `COPY` Dockerfile의 끝 부분에 두세요( `CMD`).
{% endhint %}

다음 Dockerfile 명령을 Dockerfile에 병합하세요:

{% tabs %}
{% tab title="Ubuntu 베이스 이미지" %}

```dockerfile
RUN apt-get update
RUN apt-get install openssh-server sudo -y

RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000
RUN echo 'tester:$ecureP@ss' | chpasswd
# 비밀번호를 변경하는 것을 잊지 마세요 ^

EXPOSE 22
```

{% endtab %}

{% tab title="Alpine 베이스 이미지" %}

```dockerfile
RUN apk --update add --no-cache openssh bash
RUN sed -i s/#PermitRootLogin.*/PermitRootLogin\ yes/ /etc/ssh/sshd_config

RUN echo "tester:$ecureP@ss" | chpasswd
# 비밀번호를 변경하는 것을 잊지 마세요 ^

EXPOSE 22
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
`EXPOSE` 는 포트를 자동으로 공개하지 않으며, Docker 엔진과 개발자를 위한 힌트입니다.
{% endhint %}

컨테이너에서 SSH 서비스를 시작하는 작업도 필요합니다:

{% tabs %}
{% tab title="Dockerfile에서 시작하기(Unity 플러그인)" %}
{% code title="Dockerfile" %}

```docker
CMD [ \
  "/bin/bash", "-c", \
  "env;service ssh start;/path/to/server-executable" \
]
# 환경 변수를 출력하고, SSH를 시작한 다음 게임 서버를 시작합니다
```

{% endcode %}
{% endtab %}

{% tab title=".sh 셸 스크립트에서 시작하기(Unreal)" %}
{% code title="StartServer.sh" %}

```sh
service ssh start
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
SSH 서비스를 `RUN` 명령으로 시작할 수는 없습니다. 빌드 시점에만 실행되기 때문입니다.
{% endhint %}

✅ 이제 `docker build`, 그리고 테스트 `docker run`  를 로컬에서 실행한 뒤, `ssh localhost:22`.

{% hint style="danger" %}
:x: **하지 마세요 - 기존 태그를 덮어쓰거나 사용 `최신` 태그** - 이렇게 하면 오래된 캐시가 배포됩니다.\
:white\_check\_mark: **하세요 - 버전 태그를 항상 증가시키세요** 그리고 새 빌드를 배포하세요.
{% endhint %}

{% hint style="success" %}
**이미지를 레지스트리에 푸시하기 전에 로컬에서(그리고 안전하게) 먼저 문제를 진단하세요.**
{% endhint %}

### 클라우드에 배포

만약 [#test-locally](#test-locally "mention")로 성공하지 못했다면, 배포 환경에서 테스트할 수 있습니다.

✅ [Docker 레지스트리에 로그인하세요](https://app.edgegap.com/registry-management/repositories/list) 및  `docker push`  새 태그를:

{% code title="" %}

```sh
username='robot$<REGISTRY_ORGANIZATION_ID>+client-push';
token='<REGISTRY_TOKEN>';

project='<REGISTRY_PROJECT>';
image='<MY_IMAGE_NAME>';
tag='<MY_TAG>';

echo "$token" | docker login registry.edgegap.com -u "$username" --password-stdin 2>&1;
docker push "${registry}/${project}/${image}:${tag}";
```

{% endcode %}

✅ [대시보드를 통해 이 이미지에 대한 새 테스트 앱 버전을 만드세요.](https://app.edgegap.com/application-management/applications/list)

* 22/TCP에 대한 포트 매핑을 추가해 `-p` 옵션을 `docker run`.

✅ [배포](https://app.edgegap.com/deployment-management/deployments/create) 와 동일하게 만들고, 외부 SSH 포트가 할당된 URL 또는 IP를 사용해 `ssh`.

✅ 테스트가 끝나면 배포를 중지하고 테스트 이미지를 삭제하세요.
