---
myst:
  html_meta:
    "description lang=en": "Building and running Docker images"
    "keywords": "Docker, containers, Nix, reproducible, build, tutorial"
---

(nixos-docker-images)=
# Docker 이미지 빌드하고 실행하기

```{contributors}
:authors: domenkozar
```

[Docker](https://www.docker.com/)는 컨테이너를 빌드, 관리, 배포하는 데 사용하는 도구와 서비스의 모음입니다.

많은 클라우드 플랫폼이 Docker 기반 컨테이너 호스팅을 제공합니다. Docker 컨테이너를 만드는 일은 재현 가능한 소프트웨어를 빌드할 때 흔히 하는 작업입니다. 이 튜토리얼에서는 Nix를 사용하여 Docker 컨테이너를 빌드하는 방법을 배웁니다.

## 사전 요구 사항

Nix와 [Docker](https://docs.docker.com/get-docker/)가 모두 설치되어 있어야 합니다. Docker는 `nixpkgs`에서 제공되며, NixOS에서는 이 방법으로 설치하는 것을 권장합니다. 하지만 다른 Linux 배포판이나 macOS를 사용하는 경우에는 운영 체제의 네이티브 Docker 설치를 사용할 수도 있습니다.

## 첫 번째 컨테이너 빌드하기

[Nixpkgs](https://github.com/NixOS/nixpkgs)는 Docker 이미지를 만들 수 있도록 `dockerTools`를 제공합니다:

```nix
{ pkgs ? import <nixpkgs> { }
, pkgsLinux ? import <nixpkgs> { system = "x86_64-linux"; }
}:

pkgs.dockerTools.buildImage {
  name = "hello-docker";
  config = {
    Cmd = [ "${pkgsLinux.hello}/bin/hello" ];
  };
}
```

:::{note}
**macOS**나 `x86_64-linux` 이외의 플랫폼을 사용하는 경우에는 다음 중 하나를 해야 합니다:

- Linux에서 빌드하려면 [원격 빌드 머신을 설정하십시오](distributed-build-setup-tutorial)
- `pkgsLinux.hello`를 `pkgs.pkgsCross.musl64.hello`로 바꿔서 [Linux용으로 크로스 컴파일하십시오](cross-compilation)
:::

`dockerTools.buildImage`를 호출하고 몇 가지 매개변수를 전달합니다:

- 이미지의 `name`
- 이미지가 시작되면 컨테이너 안에서 실행할 명령 `Cmd`를 포함하는 `config` 여기서는 `nixpkgs`의 GNU hello 패키지를 참조하고 그 실행 파일을 컨테이너 안에서 실행합니다.

이 내용을 `hello-docker.nix`에 저장하고 빌드하십시오:

```shell-session
$ nix-build hello-docker.nix
these derivations will be built:
  /nix/store/qpgdp0qpd8ddi1ld72w02zkmm7n87b92-docker-layer-hello-docker.drv
  /nix/store/m4xyfyviwbi38sfplq3xx54j6k7mccfb-runtime-deps.drv
  /nix/store/v0bvy9qxa79izc7s03fhpq5nqs2h4sr5-docker-image-hello-docker.tar.gz.drv
warning: unknown setting 'experimental-features'
building '/nix/store/qpgdp0qpd8ddi1ld72w02zkmm7n87b92-docker-layer-hello-docker.drv'...
No contents to add to layer.
Packing layer...
Computing layer checksum...
Finished building layer 'hello-docker'
building '/nix/store/m4xyfyviwbi38sfplq3xx54j6k7mccfb-runtime-deps.drv'...
building '/nix/store/v0bvy9qxa79izc7s03fhpq5nqs2h4sr5-docker-image-hello-docker.tar.gz.drv'...
Adding layer...
tar: Removing leading `/' from member names
Adding meta...
Cooking the image...
Finished.
/nix/store/y74sb4nrhxr975xs7h83izgm8z75x5fc-docker-image-hello-docker.tar.gz
```

이미지 태그(`y74sb4nrhxr975xs7h83izgm8z75x5fc`)는 Nix 빌드 해시를 가리키며, Docker 이미지가 Nix 빌드와 일치하도록 보장합니다. 출력의 마지막 줄에 있는 스토어 경로가 Docker 이미지를 가리킵니다.

## 컨테이너 실행하기

컨테이너를 사용하려면 `nix-build`가 만든 기본 `result` 심볼릭 링크에서 이 이미지를 Docker의 이미지 레지스트리로 불러오십시오:

```shell-session
$ docker load < result
Loaded image: hello-docker:y74sb4nrhxr975xs7h83izgm8z75x5fc
```

`result`가 있는지에 의존하지 않도록 스토어 경로를 사용하여 이미지를 불러올 수도 있습니다:

```shell-session
$ docker load < /nix/store/y74sb4nrhxr975xs7h83izgm8z75x5fc-docker-image-hello-docker.tar.gz
Loaded image: hello-docker:y74sb4nrhxr975xs7h83izgm8z75x5fc
```

더 편리하게는 모든 작업을 명령 하나로 할 수도 있습니다. 이 방법의 장점은 변경 사항이 있으면 `nix-build`가 이미지를 다시 빌드하고 새 스토어 경로를 `docker load`에 전달한다는 것입니다:

```shell-session
$ docker load < $(nix-build hello-docker.nix)
Loaded image: hello-docker:y74sb4nrhxr975xs7h83izgm8z75x5fc
```

이제 이미지를 Docker에 불러왔으므로 실행할 수 있습니다:

```shell-session
$ docker run -t hello-docker:y74sb4nrhxr975xs7h83izgm8z75x5fc
Hello, world!
```

## Docker 이미지 다루기

Docker 이미지를 다루는 방법에 대한 일반적인 소개는 이 튜토리얼에서 다루지 않습니다. 그런 내용은 [공식 Docker 문서](https://docs.docker.com/)를 참고하는 것이 훨씬 좋습니다.

Nix로 Docker 이미지를 빌드할 때는 Nix가 Docker 생태계 안에서 Dockerfile의 기능을 대신하므로 아마 `Dockerfile`을 작성하지 않게 될 것입니다. 그럼에도 Dockerfile의 구조를 이해해 두면 Nix가 Dockerfile의 각 함수를 어떻게 대체하는지 이해하는 데 여전히 도움이 될 수 있습니다. 반면 Docker CLI, Docker Compose, Docker Swarm, Docker Hub는 사용 사례에 따라 여전히 쓸모가 있을 수 있습니다.

## 다음 단계

- `dockerTools` 사용법에 대한 자세한 내용은 [참조 문서](https://nixos.org/nixpkgs/manual/#sec-pkgs-dockerTools)에서 확인할 수 있습니다.
- [Nix로 빌드한 Docker 이미지 예제](https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/docker/examples.nix)를 더 둘러보셔도 좋습니다.
- Nix를 일급으로 지원하는 `docker-compose` 래퍼인 [Arion](https://docs.hercules-ci.com/arion/)을 살펴보십시오.
- {ref}`GitHub Actions를 사용한 CI <github-actions>`에서 Docker 이미지를 빌드하십시오.
