패키지 레지스트리의 PyPI 패키지
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
Python 패키지 인덱스(PyPI)는 Python의 공식 서드파티 소프트웨어 저장소입니다. 패키지 레지스트리는 다음과 함께 작동합니다: pip 및 twine 클라이언트가 사용하는 특정 API 엔드포인트 문서는 PyPI API 문서를 참조하세요.
Python 패키지 인덱스(PyPI)는 Python의 공식 서드파티 소프트웨어 저장소입니다. GitLab PyPI 패키지 레지스트리를 사용하여 GitLab 프로젝트, 그룹 및 조직에서 Python 패키지를 게시하고 공유할 수 있습니다. 이 통합을 통해 코드와 함께 Python 종속성을 관리하여 GitLab 내에서 Python 개발을 위한 원활한 워크플로를 제공합니다.
패키지 레지스트리는 다음과 함께 작동합니다:
pip 및 twine 클라이언트가 사용하는 특정 API 엔드포인트 문서는 PyPI API 문서를 참조하세요.
PyPI 패키지를 빌드하는 방법을 알아보세요.
패키지 요청 전달 보안 공지#
GitLab PyPI 패키지 레지스트리를 사용할 때, GitLab 레지스트리에서 찾을 수 없는 패키지 요청은 자동으로 pypi.org로 전달됩니다. 이 동작으로 인해 --index-url 플래그를 사용하더라도 pypi.org에서 패키지가 다운로드될 수 있습니다.
비공개 패키지 작업 시 최대 보안을 위해:
- 그룹 설정에서 패키지 전달을 끕니다.
- 패키지를 설치할 때
--index-url및--no-index플래그를 모두 사용합니다.
사전 요구 사항:
- 그룹에 대한 Owner 권한이 있어야 합니다.
패키지 요청 전달을 끄려면:
- 상단 바에서 검색 또는 이동을 선택하고 그룹을 찾습니다.
- 왼쪽 사이드바에서 Settings > Packages and registries를 선택합니다.
- Package forwarding 아래에서 Forward PyPI package requests 체크박스를 지웁니다.
Admin 영역에서 패키지 전달을 끄는 방법은 패키지 전달 제어를 참조하세요.
GitLab 패키지 레지스트리로 인증#
GitLab 패키지 레지스트리와 상호 작용하기 전에 인증해야 합니다.
다음으로 인증할 수 있습니다:
- 범위가
api로 설정된 개인 액세스 토큰. - 범위가
read_package_registry,write_package_registry또는 둘 다로 설정된 배포 토큰. - CI/CD Job 토큰.
여기에 문서화된 방법 이외의 인증 방법을 사용하지 마세요. 문서화되지 않은 인증 방법은 나중에 제거될 수 있습니다.
GitLab 토큰으로 인증하려면:
TWINE_USERNAME및TWINE_PASSWORD환경 변수를 업데이트합니다.
예를 들면:
run:
image: python:latest
variables:
TWINE_USERNAME: <personal_access_token_name>
TWINE_PASSWORD: <personal_access_token>
script:
- pip install build twine
- python -m build
- python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*
run:
image: python:latest
variables:
TWINE_USERNAME: <deploy_token_username>
TWINE_PASSWORD: <deploy_token>
script:
- pip install build twine
- python -m build
- python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*
run:
image: python:latest
variables:
TWINE_USERNAME: gitlab-ci-token
TWINE_PASSWORD: $CI_JOB_TOKEN
script:
- pip install build twine
- python -m build
- python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*
그룹에 대한 인증#
그룹의 패키지 레지스트리로 인증하려면:
- 패키지 레지스트리로 인증하되, 프로젝트 URL 대신 그룹 URL을 사용합니다:
https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi
PyPI 패키지 게시#
twine으로 패키지를 게시할 수 있습니다.
사전 요구 사항:
- 패키지 레지스트리로 인증해야 합니다.
- 버전 문자열이 유효해야 합니다.
- 패키지:
- 5GB 이하입니다.
description이 4000자 이하입니다. 더 긴description문자열은 잘립니다.- 패키지 레지스트리에 아직 게시되지 않았습니다. 동일한 버전의 패키지를 게시하려고 하면
400 Bad Request가 반환됩니다.
PyPI 패키지는 프로젝트 ID를 사용하여 게시됩니다. 프로젝트가 그룹에 있는 경우, 프로젝트 레지스트리에 게시된 PyPI 패키지는 그룹 레지스트리에서도 사용할 수 있습니다. 자세한 내용은 그룹에서 설치를 참조하세요.
패키지를 게시하려면:
-
리포지터리 소스를 정의하고
~/.pypirc파일을 편집하여 다음을 추가합니다:[distutils] index-servers = gitlab [gitlab] repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi -
twine으로 패키지를 업로드합니다:
python3 -m twine upload --repository gitlab dist/*패키지가 성공적으로 게시되면 다음과 같은 메시지가 표시됩니다:
Uploading distributions to https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi Uploading mypypipackage-0.0.1-py3-none-any.whl 100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.58k/4.58k [00:00<00:00, 10.9kB/s] Uploading mypypipackage-0.0.1.tar.gz 100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.24k/4.24k [00:00<00:00, 11.0kB/s]
패키지가 패키지 레지스트리에 게시되고 Packages and registries 페이지에 표시됩니다.
인라인 인증으로 게시#
리포지터리 소스를 정의하기 위해 .pypirc 파일을 사용하지 않은 경우, 인라인 인증으로 리포지터리에 게시할 수 있습니다:
TWINE_PASSWORD=<personal_access_token, deploy_token, or $CI_JOB_TOKEN> \
TWINE_USERNAME=<username, deploy_token_username, or gitlab-ci-token> \
python3 -m twine upload --repository-url https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi dist/*
동일한 이름과 버전의 패키지 게시#
동일한 이름과 버전의 패키지가 이미 있는 경우 패키지를 게시할 수 없습니다.
먼저 기존 패키지를 삭제해야 합니다.
동일한 패키지를 두 번 이상 게시하려고 하면 400 Bad Request 오류가 발생합니다.
PyPI 패키지 설치#
기본적으로 GitLab 패키지 레지스트리에서 PyPI 패키지를 찾을 수 없는 경우, 요청은 pypi.org로 전달됩니다. 요청 전달을 방지하는 방법에 대한 자세한 내용은 패키지 요청 전달 및 보안 공지를 참조하세요.
이 동작:
- 모든 GitLab 인스턴스에 대해 기본적으로 활성화됩니다.
- 그룹의 Packages and registries 설정에서 구성할 수 있습니다.
--index-url플래그를 사용할 때도 적용됩니다.
관리자는 Continuous Integration 설정에서 이 동작을 전역으로 비활성화할 수 있습니다. 그룹 Owner는 그룹 설정의 Packages and registries 섹션에서 특정 그룹에 대해 이 동작을 비활성화할 수 있습니다.
--index-url 옵션을 사용할 때 기본 포트인 경우 포트를 지정하지 마세요. http URL은 기본값이 80이고 https URL은 기본값이 443입니다.
프로젝트에서 설치#
패키지의 최신 버전을 설치하려면 다음 명령을 사용합니다:
pip install --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple --no-deps <package_name>
<package_name>은 패키지 이름입니다.<personal_access_token_name>은read_api범위의 개인 액세스 토큰 이름입니다.<personal_access_token>은read_api범위의 개인 액세스 토큰입니다.<project_id>는 프로젝트의 URL 인코딩된 경로(예:group%2Fproject) 또는 프로젝트 ID(예:42)입니다.
이 명령들에서 --index-url 대신 --extra-index-url을 사용할 수 있습니다. 가이드를 따르고 MyPyPiPackage 패키지를 설치하려는 경우 다음을 실행할 수 있습니다:
pip install mypypipackage --no-deps --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
이 메시지는 패키지가 성공적으로 설치되었음을 나타냅니다:
Looking in indexes: https://<personal_access_token_name>:****@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
Collecting mypypipackage
Downloading https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/files/d53334205552a355fee8ca35a164512ef7334f33d309e60240d57073ee4386e6/mypypipackage-0.0.1-py3-none-any.whl (1.6 kB)
Installing collected packages: mypypipackage
Successfully installed mypypipackage-0.0.1
그룹에서 설치#
그룹에서 패키지의 최신 버전을 설치하려면 다음 명령을 사용합니다:
pip install --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi/simple --no-deps <package_name>
이 명령에서:
<package_name>은 패키지 이름입니다.<personal_access_token_name>은read_api범위의 개인 액세스 토큰 이름입니다.<personal_access_token>은read_api범위의 개인 액세스 토큰입니다.<group_id>는 그룹 ID입니다.
이 명령들에서 --index-url 대신 --extra-index-url을 사용할 수 있습니다.
가이드를 따르고 MyPyPiPackage 패키지를 설치하려는 경우 다음을 실행할 수 있습니다:
pip install mypypipackage --no-deps --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi/simple
패키지 이름#
GitLab은 Python 정규화 이름(PEP-503)을 사용하는 패키지를 찾습니다.
문자 -, _, .은 모두 동일하게 취급되고 반복 문자는 제거됩니다.
my.package에 대한 pip install 요청은 my-package, my_package, my....package와 같이 세 문자 중 하나와 일치하는 패키지를 찾습니다.
보안 영향#
PyPI 패키지를 설치할 때 --extra-index-url과 --index-url을 사용할 때의 보안 영향은 중요하며 자세히 이해할 가치가 있습니다:
--index-url: 이 옵션은 기본 PyPI 인덱스 URL을 지정된 URL로 대체합니다. 기본적으로 켜져 있는 GitLab 패키지 전달 설정은 패키지 레지스트리에 없는 패키지를 PyPI에서 여전히 다운로드할 수 있습니다. GitLab에서만 패키지가 설치되도록 하려면:- 그룹 설정에서 패키지 전달을 비활성화합니다.
--index-url및--no-index플래그를 함께 사용합니다.
--extra-index-url: 이 옵션은 기본 PyPI 인덱스와 함께 검색할 추가 인덱스를 추가합니다. 기본 PyPI와 추가 인덱스 모두에서 패키지를 확인하므로 덜 안전하고 의존성 혼동 공격에 더 취약합니다.
비공개 패키지를 사용할 때 다음 모범 사례를 고려하세요:
- 그룹의 패키지 전달 설정을 확인합니다.
- 비공개 패키지를 설치할 때
--no-index및--index-url플래그를 함께 사용합니다. pip debug를 사용하여 패키지 소스를 정기적으로 감사합니다.
PyPI 패키지 삭제#
사전 요구 사항:
- Maintainer 또는 Owner 권한이 있어야 합니다.
패키지를 삭제하기 전에 관련 보안 위험을 이해해야 합니다.
패키지를 삭제하려면 다음 중 하나를 사용합니다:
CI/CD 파이프라인에서 비공개 PyPI 패키지 설치#
CI/CD Job 토큰을 사용하여 CI/CD 파이프라인에서 비공개 PyPI 패키지를 설치할 수 있습니다. Job 토큰은 자동으로 인증되며 동일한 최상위 그룹 내의 다른 프로젝트의 패키지에도 액세스할 수 있습니다.
사전 요구 사항:
- 패키지가 다른 프로젝트에 있는 경우, 해당 프로젝트는 프로젝트의 Job 토큰을 허용해야 합니다. 자세한 내용은 Job 토큰 액세스 제어를 참조하세요.
- CI/CD Job 토큰으로 인증할 때 사용자 이름은
gitlab-ci-token이어야 합니다.
인라인 자격 증명 사용#
pip install 명령에 직접 CI_JOB_TOKEN을 전달합니다:
install:
image: python:latest
script:
- pip install <package_name> --index-url https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
그룹의 모든 프로젝트에서 패키지를 포함하는 그룹 인덱스에서 설치하려면:
install:
image: python:latest
script:
- pip install <package_name> --index-url https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi/simple
CI/CD에서 .netrc 파일 사용#
.netrc는 requirements.txt를 자격 증명 없이 유지하므로 동일한 파일이 로컬과 CI/CD 파이프라인 모두에서 작동합니다. pip는 .netrc 파일을 자동으로 읽어 주어진 호스트 이름의 자격 증명을 찾습니다. 자세한 내용은 .netrc 지원을 참조하세요.
.gitlab-ci.yml에서 before_script에 .netrc 파일을 만듭니다:
install:
image: python:latest
before_script:
- |
echo "machine gitlab.example.com
login gitlab-ci-token
password ${CI_JOB_TOKEN}" > ~/.netrc
script:
- pip install -r requirements.txt
requirements.txt는 자격 증명 없이 GitLab 레지스트리를 참조합니다:
--extra-index-url https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
package-name==1.0.0
로컬 개발의 경우, api 범위의 개인 액세스 토큰을 사용하는 ~/.netrc 파일을 만듭니다:
machine gitlab.example.com
login <personal_access_token_name>
password <personal_access_token>
.netrc 파일은 호스트 이름당 하나의 자격 증명 세트를 구성합니다. 여러 GitLab 인스턴스에서 패키지로 인증해야 하는 경우 각 호스트 이름에 대해 별도의 machine 항목을 추가합니다.
Docker 빌드 중 비공개 패키지 설치#
비공개 PyPI 패키지가 필요한 Docker 이미지를 빌드할 때 빌드 인수로 CI_JOB_TOKEN을 전달합니다:
build:
image: docker:latest
services:
- docker:dind
script:
- docker build --build-arg CI_JOB_TOKEN=$CI_JOB_TOKEN -t my-image .
Dockerfile에서 토큰을 사용하여 레지스트리로 인증합니다:
ARG CI_JOB_TOKEN
RUN pip install <package_name> --index-url https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
빌드 인수는 이미지 히스토리에 표시될 수 있습니다. 프로덕션 이미지의 경우, 토큰이 최종 이미지 레이어에 없도록 멀티 스테이지 빌드를 사용합니다.
requirements.txt 사용#
pip가 공개 레지스트리에 액세스하도록 하려면 requirements.txt 파일에 --extra-index-url 파라미터와 레지스트리 URL을 추가합니다.
--extra-index-url https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple
package-name==1.0.0
이것이 비공개 레지스트리인 경우 몇 가지 방법으로 인증할 수 있습니다. 예를 들면:
-
개인 액세스 토큰을 사용하는
requirements.txt파일:--extra-index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple package-name==1.0.0 -
개인 액세스 토큰을 사용하는
~/.netrc파일:machine gitlab.example.com login <personal_access_token_name> password <personal_access_token>
PyPI 패키지 버전 관리#
적절한 버전 관리는 PyPI 패키지를 효과적으로 관리하는 데 중요합니다. 패키지가 올바르게 버전 관리되도록 다음 모범 사례를 따르세요.
시맨틱 버전 관리(SemVer) 사용#
패키지에 시맨틱 버전 관리를 채택합니다. 버전 번호는 MAJOR.MINOR.PATCH 형식이어야 합니다:
- 호환되지 않는 API 변경의 경우
MAJOR버전을 증가시킵니다. - 하위 호환 가능한 새 기능의 경우
MINOR버전을 증가시킵니다. - 하위 호환 가능한 버그 수정의 경우
PATCH버전을 증가시킵니다.
예: 1.0.0, 1.1.0, 1.1.1.
새 프로젝트는 버전 0.1.0으로 시작하세요. 이는 API가 아직 안정적이지 않은 초기 개발 단계를 나타냅니다.
유효한 버전 문자열 사용#
버전 문자열이 PyPI 표준에 따라 유효한지 확인합니다. GitLab은 버전 문자열을 검증하기 위해 특정 정규식을 사용합니다:
\A(?:
v?
(?:([0-9]+)!)? (?# epoch)
([0-9]+(?:\.[0-9]+)*) (?# release segment)
([-_\.]?((a|b|c|rc|alpha|beta|pre|preview))[-_\.]?([0-9]+)?)? (?# pre-release)
((?:-([0-9]+))|(?:[-_\.]?(post|rev|r)[-_\.]?([0-9]+)?))? (?# post release)
([-_\.]?(dev)[-_\.]?([0-9]+)?)? (?# dev release)
(?:\+([a-z0-9]+(?:[-_\.][a-z0-9]+)*))? (?# local version)
)\z}xi
이 정규식 편집기를 사용하여 정규식을 실험하고 버전 문자열을 테스트할 수 있습니다.
정규식에 대한 자세한 내용은 Python 문서를 참조하세요.
지원되는 CLI 명령#
GitLab PyPI 리포지터리는 다음 CLI 명령을 지원합니다:
twine upload: 레지스트리에 패키지를 업로드합니다.pip install: 레지스트리에서 PyPI 패키지를 설치합니다.
문제 해결#
성능을 향상시키기 위해 pip 명령은 패키지와 관련된 파일을 캐시합니다. pip는 데이터를 자체적으로 제거하지 않습니다. 새 패키지가 설치될수록 캐시가 커집니다. 문제가 발생하면 다음 명령으로 캐시를 지웁니다:
pip cache purge
여러 index-url 또는 extra-index-url 파라미터#
여러 index-url 및 extra-index-url 파라미터를 정의할 수 있습니다.
다른 인증 토큰으로 동일한 도메인 이름(예: gitlab.example.com)을 여러 번 사용하면 pip가 패키지를 찾지 못할 수 있습니다. 이 문제는 명령 실행 중 pip가 토큰을 등록하고 저장하는 방식 때문입니다.
이 문제를 해결하려면 index-url 및 extra-index-url 값이 대상으로 하는 모든 프로젝트나 그룹의 공통 상위 그룹에서 read_package_registry 범위의 그룹 배포 토큰을 사용할 수 있습니다.
예상치 못한 패키지 소스#
GitLab 레지스트리만 사용하려 했을 때 PyPI에서 패키지가 설치되는 경우:
- 그룹의 패키지 전달 설정을 확인합니다.
- PyPI 폴백을 방지하기 위해
--no-index및--index-url플래그를 함께 사용합니다. pip debug를 사용하여 패키지 소스를 정기적으로 감사합니다.
