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
728x90

파이썬 장고가 제공하는 단위 테스트는 코드 배포전에 에러를 검출해 볼 수 있는 방법으로 무척 유용합니다. 젠킨스 빌드시에도 활용하여 자칫 로컬 환경과 원격 빌드/운영 환경의 차이에도 대응할 수 있어 장애를 막는 지름길이 되기도 합니다.

파이썬 장고의 단위 테스트를 구성해서 잘 사용하던 중, 갑자기 (원인은 알 수 없습니다 ㅜㅜ) TransactionManagementError와 함께 테스트가 지속적으로 실패하기 시작하여 열심히 구글링하고 삽질한 내용을 간략히 정리해 봅니다. 


장고 단위 테스트를 사용하기 위해서는 아래와 같은 코드를 만들게 됩니다. 참고로 코드는 장고 공식 문서에서 가져왔습니다. 이때, 실제 테스트를 수행하는 클래스는 매개변수로 TestCase 클래스의 인스턴스를 받게 됩니다. 아래의 코드에서는 TestCase 클래스를 가져왔네요.

import unittest
from django.test import Client

class SimpleTest(unittest.TestCase):
    def setUp(self):
        # Every test needs a client.
        self.client = Client()

    def test_details(self):
        # Issue a GET request.
        response = self.client.get('/customer/details/')

        # Check that the response is 200 OK.
        self.assertEqual(response.status_code, 200)

        # Check that the rendered context contains 5 customers.
        self.assertEqual(len(response.context['customers']), 5)

 

코드를 보면 실제 테스트 함수들이 클래스 내에 기술이 되어 있습니다. 제 경우 문제는 테스트 함수들이 데이터베이스에 대한 질의를 수행하는 코드를 호출하면서 발생했습니다. 일반적인 TestCase의 서브 클래스로는 데이터베이스 관련 코드를 수행하고 테스트 결과를 돌려주는데 문제가 있었습니다. 테스트가 수행되면서 발생한 에러는 아래와 같습니다.

raise TransactionManagementError(
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

 

이 에러 메세지가 참 얄미운게 내용이 좀 뭉뚱그려져 있습니다. 굉장히 명확한 에러이기 때문에 TestCase 클래스를 트랜잭션을 지원하는 것으로 변경하라고 하면 되었을 것을 저렇게 표현하고 있어서 애를 먹게 만들더군요. 이 문제에 대한 첫번째 접근은 장고 공식문서에서 가이드하는 TransactionTestCase 클래스의 사용입니다. 

https://docs.djangoproject.com/en/3.2/topics/testing/tools/#django.test.TransactionTestCase

 

제 경우는 장고 REST Framework 를 사용하고 있던 관계로 이쪽에서 필요한 클래스의 변경 작업을 진행했습니다. 기존에 에러가 발생하던 테스트 코드에서는 REST Framework가 제공하는 test 패키지의 APITestCase 클래스를 쓰고 있었습니다. 이 클래스를 APITransactionTestCase로 변경하니 에러가 말끔히 사라지고 테스트도 정상적으로 수행되기 시작했습니다.

# 기존
from rest_framework.test import APITestCase

# 변경
from rest_framework.test import APITransactionTestCase

 


TransactionManagementError로 검색을 하다보면 여러가지 문제 상황과 이에 대한 대처법들이 소개되고 있습니다. 가령 1) 테스트 테이블에 데이터를 피딩하는 과정에 문제였고 이를 수정하여 해결 했다는 분도 계셨고, 2) 테스트가 수행하는 코드 내에 try~except 구문이 사용되는 경우 transaction.atomic() 을 이용해서 코드를 변경해야 된다는 글도 있었습니다.

다양한 트러블슈팅 사례와 방법이 있는 것을 보면 에러 메세지가 조금 더 친절하게 출력되면서 원인을 빠르게 확인할 수 있었으면 어땠을까 하는 생각이 듭니다. 그래도 트러블슈팅을 하면서 또 파이썬에 대해, 장고에 대해 조금 더 알 수 있었기에 의미 없는 시간은 아니었던 것 같습니다!

파이썬과 관련하여 최근에 겪었던 다른 이슈들과 해결 방법은 아래의 글을 참고해 보시기 바랍니다!

 

M1 Apple silicon 맥북에서 파이썬 cryptography 패키지 설치가 안되는 문제 / python cryptography package installa

M1 silicon 맥북에서는 안되는게 참 많습니다. 새로운 CPU 아키텍쳐라서 여기저기서 패키지들이 오동작하거나 설치가 안되는 문제들이 많이 발생합니다. 오늘의 주인공인 파이썬 cryptography 패키지

ondemand.tistory.com

 

 

애플실리콘 M1 맥북에서 파이썬 magic 패키지가 로딩되지 않는 현상

애플실리콘 기반의 맥북이 등장하면서 세상이 참 행복해졌습니다. 베터리도 오래가고 이륙하지도 않고... 이렇게 쾌적한 맥 운영체제는 간만에 느껴보는 즐거움이었습니다. 하지만 의외의 장소

ondemand.tistory.com

 

 

PIP를 통한 mysqlclient 라이브러리 설치 에러 (mysql_config not found)

새로운 개발 장비가 생기면 이전에 사용하던 장비의 환경과 동일하게 준비하는 것이 은근 번거롭습니다. 한동안 손대지 않고 있던 파이썬 Python 장고 Django 프레임웍으로 개발된 코드를 새 장비

ondemand.tistory.com

 

728x90

+ Recent posts