본문 바로가기
Python

[Python] Private PYPI

by 혀나Lee 2016. 11. 9.

PYPI는 the Python Package Index. 의 줄임말입니다. PYPI 는 간단하게 python 관련 패키지들이 모여있는 저장소라고 할 수 있습니다. python 개발자들은 자신이 개발한 python 모듈을 PYPI에 업로드 할 수 있으며 PYPI에 저장된 모듈은 누구에게나 공개되어 있습니다. 회사 내에서와 같이 보안이 중요한 곳에서 자신이 만든 모듈을 private 하게 구축하는 방법을 설명하겠습니다. 


PYPI 설치

$ docker pull codekoala/pypi


docker 를 사용하여 pypi 이미지를 다운 받습니다.

docker 설정

docker 에 대한 내용은 따로 정리하도록 하겠습니다.

Usage[각주:1]

$ sudo mkdir -p /srv/pypi                    # 패키지를 담는 디렉토리를 로컬에 생성합니다.
$ sudo touch /srv/pypi/.htaccess         # 패키지를 추가하기 위한 credential 파일
$ docker run -t -i -d \
-h pypi.local \                               # hostname
-v /srv/pypi:/srv/pypi:rw \           # 볼륨을 설정해 호스트 디렉토리를 pypi 컨테이너와 공유합니다. :rw로 읽기, 쓰기 설정을 해줍니다.
-p 8080:80 \                               # expose port 80 as port 8080
--name pypi \                              # 컨테이너 이름
codekoala/pypi                           


자세한 설정 방법은 docker hub 사이트에서 pypi 이미지를 검색하여 확인할 수 있습니다.

  • mkdir의 -p 옵션: 상위 디렉토리를 포함한 디렉토리를 생성 
    • -p /srv/pypi: /srv 디렉토리를 생성한 후, /srv 디렉토리 내에 pypi 디렉토리를 생성
  • touch: 파일의 날짜, 시간 정보를 변경하는 명령어
    • 옵션이 없는 경우: 파일의 최근 변경된 시간을 서버의 현재 시간으로 변경하고 파일의 크기가 0인 빈 파일을 생성

Dockerfile

Dockerfile을 통해 위의 명령어 실행 이유를 확인할 수 있다.

FROM codekoala/saltyarch

MAINTAINER Josh VanderLinden <codekoala@gmail.com>


RUN pacman -Sy --noconfirm --needed python-pip python-passlib && pip install -U pypiserver && mkdir -p /srv/pypi && rm -rf /var/cache/pacman/*


EXPOSE 80

VOLUME ["/srv/pypi"]


CMD ["pypi-server", "-p", "80", "-P", "/srv/pypi/.htaccess", "/srv/pypi"]


실행되었을 시, http://localhost:8080으로 접속하여 pypi 서버를 확인할 수 있다. /srv/pypi 디렉토리에 저장을 통해 .tar, .zip, .egg 등 단순하게 파일을 추가할 수 있다.

Private PYPI 업로드

(Public)PYPI는 흔이 pip를 이용해서 설치, 관리하는 python 패키지들을 저장하고 있다. PYPI에는 74594개의 패키지가 존재한다.
일단, Private PYPI에 올릴 패키지 및 프로젝트를 준비한다. 이 때 패키지는 (Public)PYPI에 있는 패키지 파일을 말하는 것이고 프로젝트는 자신이 구현한 개인 프로젝트를 말한다. 개인 프로젝트는 다운받을 필요가 없으므로 설명하지 않겠다.

압축 파일 다운로드

압축 파일을 받아 Private PYPI에 업로드 하는 방법은 아주 쉽다. 
https://pypi.python.org/pypi 에서 Private PYPI에 업로드 하고자 하는 모듈/패키지를 검색하여 압축 파일을 다운로드 한다. Python 2.x 버전에서는 .tar 파일을 인식 못하는 경우가 있기때문에 이왕이면 .whl 파일이 받는 것이 좋다.

스크립트 작성

만약, Private PYPI에 업로드 해야하는 패키지가 많다면 일일이 압축 파일을 다운로드 받는 것은 쉽지 않다. 이럴 때 아래와 같은 패키지의 목록 및 버전 정보를 확인 후에 스크립트를 작성할 수 있을 것이다. (스크립트 작성은 아직 테스트해보지 않았기 때문에 패키지 목록 및 버전 정보 확인을 위한 명령어만 정리했다.)
  • 패키지 목록 확인

$ wget https://pypi.python.org/simple/

$ vi index.html


<html><head><title>Simple Index</title><meta name="api-version" value="2" /></head><body>

<a href='0-.-.-.-.-.-.-.-.-.-.-.-.-0'>0-._.-._.-._.-._.-._.-._.-0</a><br/>

<a href='00smalinux'>00SMALINUX</a><br/>

<a href='01changer'>01changer</a><br/>

<a href='02exercicio'>02exercicio</a><br/>

<a href='0805nexter'>0805nexter</a><br/>

<a href='0x10c-asm'>0x10c-asm</a><br/>

<a href='1'>1</a><br/>

<a href='1020-nester'>1020-nester</a><br/>

<a href='115wangpan'>115wangpan</a><br/>

...


명령어를 작성하여 받은 index.html 파일을 열어 패키지 이름을 확인할 수 있다. (href='패키지명')
  • 버전 정보 확인

$ sudo wget https://pypi.python.org/pypi/패키지명/json
$ sudo wget https://pypi.python.org/pypi/roundup/json
$ vi json

{

    "info": {

        "maintainer": null,

        "docs_url": null,

        "requires_python": null,

        "maintainer_email": null,

        "cheesecake_code_kwalitee_id": null,

        "keywords": null,

        "package_url": "http://pypi.python.org/pypi/roundup",

        "author": "Ralf Schlatterbeck",

        "author_email": "rsc@runtux.com",

        "download_url": "http://pypi.python.org/pypi/roundup",

        "platform": "UNKNOWN",

        "version": "1.5.1",

        "cheesecake_documentation_id": null,

        "_pypi_hidden": false,


...


    "urls": [

        {

            "has_sig": true,

            "upload_time": "2016-01-11T21:38:39",

            "comment_text": "",

            "python_version": "source",

            "url": "https://pypi.python.org/packages/bf/14/d61fac5ed2aaca8c720ac4d4077428b8fdafa356089516ba9ee630975d2a/roundup-1.5.1.tar.gz",

            "md5_digest": "54b21d185dd490ef8697f5a046607a44",

            "downloads": 693,

            "filename": "roundup-1.5.1.tar.gz",

            "packagetype": "sdist",

            "path": "bf/14/d61fac5ed2aaca8c720ac4d4077428b8fdafa356089516ba9ee630975d2a/roundup-1.5.1.tar.gz",

            "size": 2618886

        },

        {

            "has_sig": true,

            "upload_time": "2016-01-11T21:40:16",

            "comment_text": "",

            "python_version": "any",

            "url": "https://pypi.python.org/packages/a3/9b/24ea88db250e0d70106c12e3fe558fcc0eef669eb1afd6a4faba43cdff08/roundup-1.5.1.win32.exe",

            "md5_digest": "1de1f40a0918c0075793bd8a3b53781b",

            "downloads": 468,

            "filename": "roundup-1.5.1.win32.exe",

            "packagetype": "bdist_wininst",

            "path": "a3/9b/24ea88db250e0d70106c12e3fe558fcc0eef669eb1afd6a4faba43cdff08/roundup-1.5.1.win32.exe",

            "size": 2173662

        }

    ]

}


SCP 명령어 사용

SCP 명령어를 사용하여 업로드하는 방식은 수작업이라고 말할 수 있다.
PYPI에서 받은 압축 파일을 SCP 명령어로 서버의 /srv/pypi/ 폴더에 올리면 PYPI 서버에 반영이 된다.

$ scp -P 포트 <파일 경로> 계정ID@서버IP:/home/경로/
$ mv <파일> <이동할 경로>/pypi/

setup.py 사용

setup.py 파일을 만들어서 올리는 방법은 버전 관리를 하기에 아주 좋은 방법이다. 또한, 이 방법을 통해 자신의 개인 프로젝트를 Private PYPI에 올릴 수 있다.

관리자 설정

서버 관리자는 사용자의 아이디와 비밀번호를 정의해야 한다.

# 명령어 사용

$ htpasswd -s htaccess yourusername


# vi 로 작성

# http://www.htaccesstools.com/htpasswd-generator/ URI에 접속하여 사용자의 아이디와 비밀번호를 입력하고 나온 결과를 복사한다.

# 복사한 값을 아래 경로에 .htaccess 파일을 만든다.

$ cd /srv/pypi

$ sudo vi .htaccess


복사한 내용 (예, 사용자ID:암호화된비밀번호)

사용자 설

  • 윈도우

[distutils]

index-servers =

    pypi

    internal


[pypi]

username:pypiusername

password:pypipassword


[internal]

repository: http://<private pypi 서버 IP>:<port>

username:<할당된ID>

password:<비밀번호>

.pypirc 저장하고 C:\Users\(로그인된 사용자 아이디) 저장합니다

) C:\Users\lha  저장

  • 리눅스

$ sudo vi ~/.pypirc

[distutils]

index-servers =

    pypi

    internal


[pypi]

username:pypiusername

password:pypipassword


[internal]

repository: http://<private pypi 서버 IP>:<port>

username:<할당된ID>

password:<비밀번호>

setup.py 설정

자신이 Private PYPI에 업로드하고 싶은 파일(프로젝트)와 같은 경로 상에 setup.py 파일을 만든 후 아래와 같이 작성해줍니다.

setup (

        name               = 'mypackage', 

        version             = '1.0.0',

        py_modules      = ['mypackage'], //name py_modules 동일한 이름이여야 합니다.

        author              = 'lha',

        author_email     = 'lha@lha.com',

        description        = '설명',

)

서버 업로드

setup.py 파일을 설정한 후 명령어를 통해 Private PYPI 서버에 배포(업로드)한다.

.tar 업로드

$ python setup.py sdist register -r internal upload -r internal
  • sdist: setup.py 에 설정된 패키지(파일)을 압축함
  • register -r internal: 서버에 접속할 수 있는지 확인
  • upload -r internal: 패키지(파일) 업로드
위의 명령어는 .tar 로 생성하여 올리기 때문에 python3 에서만 사용이 가능하다. python2, 3 모두 사용가능한 wheel 타입으로 올리는 것이 가장 좋다.

.whl 업로드

$ pip3 install wheel

# setup.py 와 동일한 경로에 생성
$ vi setup.cfg 

[bdist_wheel]
universal = 1

# 업로드 명령어
$ python setup.py sdist bdist_wheel register -r internal upload -r internal

주의할 점

setup.py 에서 사용하는 라이브러리는 from distutils.core import setup 이다. 해당 라이브러리 사용시 에러가 발생하면 from setuptools import setup 을 사용한다.
wheel로 압축할 경우, from distutils.core import setup 이부분을 from setuptools import setup 같이 변경하여 줍니다.

다른 서버에서 Private PYPI에 있는 패키지 설치하기

# easy_install 설치: https://pypi.python.org/pypi/distribute 
$ python setup install
$ easy_install pip

# pip 설치 in ubuntu
$ sudo apt-get install python-pip

pip 를 이용하여 다운로드 받을 경우

$ pip download --trusted-host <pypi 서버 IP> --index-url <pypi 주소>/simple/ <패키지명>

# django에서 requirements.txt 를 사용할 경우

$ pip install --trusted-host <pyip 서버 IP> -i <pypi 주소>/simple -r $PATH/requirements.txt


# 예

$ pip install --trusted-host 127.0.0.1 -i http://127.0.0.1:8080/simple imi

$ pip install --trusted-host 127.0.0.1 -i http://127.0.0.1:8080/simple -r $PATH/requirements.txt

easy_install 을 사용하여 다운로드 받을 경우

$ easy_install -i <pypi 주소>/simple 패키지명

# 예
$ easy_instll -i http://127.0.0.1:8080/simple imi

버전 확인

$ pip show <패키지명>

# setup.py 에 작성된 내용이 나온다. with 패키지가 설치된 경로

Adding Thrid Party Packages

아래의 명령어를 사용하여 해당 패키지를 미러링할 수 있다.

$ pip install -d /srv/pypi <패키지명>

미러링된 패키지 업데이트 하기

$ pypi-server -U /srv/pypi

저장소에 있는 각 패키지들은 업데이트를 확인하고 업데이트 합니다.


  1. https://hub.docker.com/r/codekoala/pypi/ [본문으로]

댓글