728x90

서버의 환경을 해치지 않으면서
이미지로 공급되는 어플리케이션간의 통신을 
구현해야 하는 경우가 많이 있습니다. 

외부로 노출은 nginx로 제한하고
실제 각 어플리케이션 접근을
nginx의 location 지시자를 이용하는 경우가 
대표적인 시나리오입니다. 

사용자에 대한 노출은 nginx endpoint 만하고 싶다면?

docker-compose로 다수 컨테이너 구동하기

이 구성을 위해서는 docker-compose를 이용해서 
복수의 컨테이너를 하나의 설정으로 만들어
컨테이너를 배포하는 것이 눈에 잘 들어오고 편리합니다. 

속도 측정을 위한 오픈소스 어플리케이션인
librespeed를 별도의 컨테이너로 띄워두고
nginx도 별도로 구동하기 위해서는 
다음과 같은 설정을 활용할 수 있습니다. 

version: "2"
services:
  nginx:
    container_name: nginx-test
    image: nginx
    ports:
    - 443:443
  speedtest:
    container_name: speedtest
    image: adolfintel/speedtest
    environment:
    - MODE=standalone
    ports:
    - 80:80

nginx의 설정파일은 아래와 같습니다.

upstream speedtest {
    server speedtest:80;
}

server {
    listen      443 ssl;
    server_name example.com;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    ssl_certificate /etc/nginx/cert/fullchain.crt;
    ssl_certificate_key /etc/nginx/cert/private.key;

    access_log  /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log debug;

    location / {
        proxy_pass http://speedtest;
    }
}

컨테이너가 잘 뜰까요? 그렇지 않습니다. 
nginx는 speedtest 이름을 찾을 수 없어서 
업스트림 호스트를 찾을 수 없다는 에러를 뿜습니다.

2022/06/18 03:16:21 [emerg] 1#1: host not found in upstream "speedtest:80" in /etc/nginx/conf.d/default.conf:7
2022/06/18 03:20:00 [emerg] 1#1: host not found in upstream "speedtest:80" in /etc/nginx/conf.d/default.conf:7
2022/06/18 03:34:04 [emerg] 1#1: host not found in upstream "speedtest:80" in /etc/nginx/conf.d/default.conf:7

docker-compose 파일을 수정하여 
별도의 bridge 네트워크를 만들어
두 컨테이너가 서로 통신하도록 해보겠습니다. 

docker bridge 네트워크 구성하기

docker는 다양한 네트워크를 구성을 제공합니다. 
그 중에서 우리의 요건에 맞는 것은 bridge 네트워크입니다. 
말그대로 다리처럼 컨테이너들이 소통할 수 있는 구조입니다. 

네, 그렇다고 합니다 (출처 : https://docs.docker.com/network/bridge/)

앞서 만들었던 docker-compose 파일에 
아래와 같이 network 설정을 추가했습니다. 

version: "2"
services:
  nginx:
    container_name: nginx-test
    image: nginx
    ports:
    - 443:443
    networks:
    - backbone
  speedtest:
    container_name: speedtest
    image: adolfintel/speedtest
    environment:
    - MODE=standalone
    networks:
    - backbone
    ports:
    - 80:80
networks:
  backbone:
    driver: bridge

이번엔 잘 될까요?
설레는 마음으로 sudo docker-compose up을 해봤습니다. 
그리고 브라우저에서 도메인에 접속해보니...

떴다!

 

네, 다행히 기대한 대로 잘 동작했습니다. 
nginx 설정에서도 업스트림 서버 이름으로 
컨테이너 이름을 사용할 수 있어서 편리합니다.
컨테이너간 통신, 어렵지 않네요!

728x90
728x90

간혹 새로운 장비에서 Dockerfile 을 이용하여 이미지를 빌드해야 하는 경우가 생깁니다. 늘 사용하던 장비와 빌드하던 이미지라면 특별히 문제가 생기지 않지만 새로운 오픈소스 코드나 다른 사람이 만들어둔 Dockerfile을 생각 없이 새 장비에서 빌드하다보면 에러 메세지로 당황하기 마련입니다. 

오늘도 어김 없이 새 장비에서 Dockerfile을 이용한 이미지 빌드 실패건을 겪었는데요 미래의 저를 위해 간단하게 내용을 정리해 봅니다. 한줄 요약을 하자면 Docker의 버전이 낮아서 발생한 문제였습니다. 


새로운 오픈소스를 Docker 이미지로 빌드후 구동하기 위해 소스코드를 클론하고 make docker 명령으로 이미지 빌드를 시도했습니다. go로 개발된 프로메테우스 익스포터류의 코드였는데요 잠시 빌드가 진행되는 듯 하더니 FROM으로 지정된 이미지의 포맷이 잘못되었다는 에러 메세지와 함께 빌드가 실패했습니다. 

$ make docker
docker build -t "akamai/akamai-gtm-metrics-exporter-linux-amd64:master" \
        -f ./Dockerfile \
        --build-arg ARCH="amd64" \
        --build-arg OS="linux" \
        ./
Sending build context to Docker daemon 15.25 MB
Step 1/8 : FROM docker.io/golang:1.16.6 AS builder
Error parsing reference: "docker.io/golang:1.16.6 AS builder" is not a valid repository/tag: invalid reference format
make: *** [common-docker-amd64] Error 1

 

도커 이미지가 없어서 그런가 생각해봤지만 docker image 명령을 쳐보면 이미지가 정상적으로 로컬 환경에 저장되어 있는 것이 확인되었습니다. 이미지의 빌드 넘버가 없어서 그런가하여 도커 허브에 들어가 golang 태그를 찾아봐도 분명 존재하는 태그였습니다.

$ docker images
REPOSITORY                                   TAG                 IMAGE ID            CREATED             SIZE
docker.io/golang                             1.16.6              028d102f774a        3 days ago          862 MB
docker.io/victoriametrics/victoria-metrics   latest              27ae96c3f0f7        2 weeks ago         23.5 MB
docker.io/prom/prometheus                    latest              9dfc442be98c        3 weeks ago         189 MB
docker.io/victoriametrics/vmagent            latest              4d8a8d15c6ec        4 weeks ago         20.4 MB
docker.io/prom/node-exporter                 latest              c19ae228f069        4 months ago        26 MB

 

문제는 도커의 버전이었습니다. 빌드하려던 Dockerfile의 내용을 꼼꼼히 살펴보지 않아 Dockerfile이 멀티 스테이지 빌드가 필요하다는 것을 미처 확인하지 못했던 것이죠. 멀티 스테이지 빌드는 경량 도커 이미지를 만들기 위한 방법으로 제공되는 빌드 방식이고 도커 17버전 이상에서 지원되는 것으로 확인됩니다. 도커를 새로운 버전으로 업데이트 하고 다시 빌드를 시도해 보았습니다.

 

 

Use multi-stage builds

 

docs.docker.com

 

// 설치된 버전 확인
$ docker --version
Docker version 1.13.1, build 7d71120/1.13.1

// 설치된 docker 삭제
$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
// Community Edition 설치를 위한 repo 정보 추가
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

// 최신 버전의 docker 설치
$ sudo yum install docker-ce docker-ce-cli containerd.io

// docker daemon 구동
$ sudo systemctl start docker

// 설치된 버전 확인
$ docker --version
Docker version 20.10.7, build f0df350

// 이제 빌드가 잘 되네요!
$ make docker
docker build -t "akamai/akamai-gtm-metrics-exporter-linux-amd64:master" \
        -f ./Dockerfile \
        --build-arg ARCH="amd64" \
        --build-arg OS="linux" \
        ./
Sending build context to Docker daemon  15.25MB
Step 1/8 : FROM docker.io/golang:1.16.6 AS builder
1.16.6: Pulling from library/golang
Digest: sha256:4544ae57fc735d7e415603d194d9fb09589b8ad7acd4d66e928eabfb1ed85ff1
Status: Downloaded newer image for golang:1.16.6
 ---> 028d102f774a
Step 2/8 : WORKDIR /go/src/github.com/akamai/akamai-gtm-metrics-exporter
 ---> Running in dab4aaede8da
Removing intermediate container dab4aaede8da
...
..
...
Successfully built a005e3513fae
Successfully tagged akamai/akamai-gtm-metrics-exporter-linux-amd64:master

 

참 쉽죠!?

 

728x90
728x90

아마 대부분의 경우 리눅스 환경에 접근시 루트 권한이 아닌 계정을 쓰고 있을 겁니다. 이 환경에서 docker 명령을 쓰다보면 pull 등 기본적인 명령 수행시에도 permission denied 를 만나게 되어 sudo 를 남발해야 하는 경우가 종종 발생합니다. 조금더 쉽게 docker를 사용하고 작업을 수행하기 위해 간단한 사용자, 그룹 변경으로 문제를 회피하는 방법을 정리해 봅니다. 


제가 만났던 permission denied 는 docker pull #이미지# 를 수행하는 과정에 발생했습니다. 발생한 위치는 나름 정확하게 나와서 /var/run/docker.sock 파일에 대한 접근을 하는 과정에서 권한 문제가 발생한 것으로 확인됩니다.

$ docker pull victoriametrics/victoria-metrics
Using default tag: latest
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/create?fromImage=victoriametrics%2Fvictoria-metrics&tag=latest: dial unix /var/run/docker.sock: connect: permission denied

 

이 권한 문제는 /var/run/docker.sock 파일의 접근 권한이 root 사용자에게 한정되어 있기 때문에 발생합니다. 따라서 접근 권한을 낮추거나 실사용자가 포함된 그룹을 만들어 파일의 소유권을 변경하는 것이 가장 깔끔한 방법입니다. 

# root 사용자/그룹에게 접근 권한이 있습니다
$ ls -al /var/run/docker.sock
srw-rw---- 1 root root 0 Jul  8 16:35 /var/run/docker.sock

# docker 그룹을 새로 만들어 사용자($USER)를 docker 그룹에 추가후 파일의 권한을 변경합니다.
$ sudo /usr/sbin/groupadd -f docker
$ sudo /usr/sbin/usermod -aG docker $USER
$ sudo chown root:docker /var/run/docker.sock

# 변경후 권한은 이렇게 바뀌었습니다
$ ls -al /var/run/docker.sock
srw-rw---- 1 root docker 0 Jul  8 16:35 /var/run/docker.sock

 

이제 별 문제 없이 pull 할 수 있게 되었습니다. (만세)

$ docker pull victoriametrics/victoria-metrics
Using default tag: latest
Trying to pull repository docker.io/victoriametrics/victoria-metrics ...
latest: Pulling from docker.io/victoriametrics/victoria-metrics
5843afab3874: Pull complete
576d2fdb56fe: Pull complete
a4c69497911f: Pull complete
Digest: sha256:dedd22e46e72518f7944355dd6b236231948c6a24d60f7ca201a5c007013da64
Status: Downloaded newer image for docker.io/victoriametrics/victoria-metrics:latest

 

참고자료

 

Docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

I am new to docker. I just tried to use docker in my local machine(Ubuntu 16.04) with Jenkins. I configured a new job with below pipeline script. node { stage('Build') { docker.image('...

stackoverflow.com

 

728x90
728x90

CentOS7 환경인지 먼저 점검합니다.

$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

 

운영체제의 패키지들을 최신 버전으로 업데이트 합니다. (선택사항)

$ sudo yum update

 

docker와 docker-registry 패키지를 설치합니다

$ sudo yum -y install docker docker-registry

 

설치된 docker를 재부팅시에도 자동 실행하도록 합니다 (선택사항)

$ sudo systemctl enable docker.service
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

 

docker 서비스를 실행하고 상태를 확인해 봅니다

$ sudo systemctl start docker.service
$ systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2021-07-08 15:55:35 JST; 24s ago
     Docs: http://docs.docker.com
     ...

 

docker-registry에 등록된 이미지를 가져와서 실행해 봅니다

$ sudo docker pull centos
$ docker run -it centos /bin/bash

 

728x90

+ Recent posts