verdaccio で社内 npm レジストリを立てる
한국어 원문으로 표시합니다.
목표
npm 사내 레지스트리를 세워 연결된 동안 채우고, 위 연결을 끊은 뒤에도 잠금 파일대로 설치되는 것을 확인한다. 바깥에서 만든 잠금 파일의 주소가 어떻게 풀리는지도 직접 잰다.
왜 중요한가
node_modules 를 통째로 압축해 들고 들어가는 방식은 node 버전이 다르면 깨지고 무엇이 들어갔는지 남지 않는다. 사내 레지스트리는 패키지 단위로 쌓이고, 잠금 파일은 "무엇을 어떤 해시로" 를 적는다. 둘이 맞물리면 폐쇄망 안에서도 npm ci 가 바깥과 같은 트리를 만든다. 이 파드는 인터넷(80/443)에 닿으므로 받는 쪽 역할을 하고, 폐쇄망 쪽 확인은 채점기가 바깥으로 가는 HTTP(S)를 닫힌 프록시(127.0.0.1:9)로 보내 막은 채로 한다.
단계
/opt/verdaccio에서verdaccio@6.1.6을 설치한다(버전을 정확히 고정하고, 잠금 파일이 남아야 한다)./root/npm/config.yaml을 쓴다. 저장소는/root/npm/storage, uplinknpmjs는https://registry.npmjs.org/, 패턴'**'는 누구나 읽고npmjs를 proxy 로, 듣는 주소는127.0.0.1:4873, 로그는/root/npm/verdaccio.log파일./etc/hosts에127.0.0.1 npm.airgap.internal을 더하고 그 설정으로 verdaccio 를 띄운다.- 프로젝트
/root/npm/app(package.json 이 있어야 한다)의.npmrc에registry=http://npm.airgap.internal:4873/을 적는다. /root/npm/app에chalk@4.1.2를 설치해 사내 레지스트리가 위에서 당겨 채우게 한다.'**'패턴에서 proxy 를 빼 위 연결을 끊고 verdaccio 를 다시 띄운다./root/npm/app2에 app 의package.json·package-lock.json을 복사하고 새 캐시(/root/npm/cache2)로npm ci한다.- 바깥 레지스트리로 만든 잠금 파일을
/root/npm/outlock/에 만들고(chalk 4.1.2), 바깥이 막힌 채 사내 레지스트리로npm ci를 replace-registry-host 기본값과never로 각각 돌려 결과를/root/npm/lockhost.txt에default=ok|fail·never=ok|fail두 줄로 적는다.
참고
- 지금 적용되는 값:
npm config get registry(프로젝트 디렉터리 안에서) - verdaccio 살아 있나:
curl http://npm.airgap.internal:4873/-/ping· 다시 띄우기:pkill -x verdaccio뒤 같은 명령 - 바깥을 막고 재 보기:
HTTPS_PROXY=http://127.0.0.1:9 HTTP_PROXY=http://127.0.0.1:9 NO_PROXY=127.0.0.1,localhost,.airgap.internal npm ci ... - 흔한 실수 1:
npm install -g로 verdaccio 를 설치하기. 이 파드에서는 전역 디렉터리에 쓸 수 없어 실패합니다. 디렉터리를 정해 설치하세요. - 흔한 실수 2: uplink 를 끊은 뒤 캐시가 남은 채로 시험하기. 캐시가 받아 주면 레지스트리를 시험한 것이 아닙니다 — 새 캐시 디렉터리를 쓰세요.
반입물 1호: verdaccio 를 버전 고정으로
/opt/verdaccio 에서 verdaccio@6.1.6 을 설치한다(잠금 파일이 남아야 한다).
npm 은 디렉터리 안에서 설치하면 그 디렉터리의 node_modules 와 package-lock.json 을 만듭니다. 전역 설치는 이 파드에서 권한 때문에 실패합니다. 버전은 @ 뒤에 정확히 적으세요.
위(uplink)를 둔 프록시 레지스트리 설정
/root/npm/config.yaml 에 저장소·uplink·패턴·듣는 주소·로그 파일을 적는다.
uplinks 에 위 레지스트리의 이름과 주소를 적고, packages 의 '**' 패턴에서 그 이름을 proxy 로 가리킵니다. listen 은 호스트:포트 한 줄입니다. 로그는 type: file 로 경로를 줍니다.
사내 이름으로 레지스트리 띄우기
/etc/hosts 에 127.0.0.1 npm.airgap.internal 을 더하고 /root/npm/config.yaml 로 verdaccio 를 띄운다.
verdaccio 는 --config 로 설정 파일을 받습니다. 터미널을 닫아도 살아 있게 백그라운드로 띄우고, 레지스트리의 ping 주소로 살아 있는지 확인하세요.
프로젝트 .npmrc 로 가리키기
프로젝트 /root/npm/app(package.json 포함)의 .npmrc 에 registry=http://npm.airgap.internal:4873/ 을 적는다.
프로젝트 디렉터리의 .npmrc 는 사용자·전역 설정보다 우선합니다. 적은 뒤 그 디렉터리 안에서 npm 이 실제로 어떤 값을 쓰는지 config get 으로 확인하세요.
연결된 동안 한 번 당겨 채우기
/root/npm/app 에 chalk@4.1.2 를 설치해 사내 레지스트리가 위에서 당겨 저장소에 남기게 한다.
프로젝트의 .npmrc 가 사내 레지스트리를 가리키고 있으니 평소처럼 설치하면 됩니다. 설치 뒤 잠금 파일의 resolved 주소가 어디를 가리키는지, 레지스트리 저장소 디렉터리에 무엇이 생겼는지 보세요.
위 연결을 끊어 폐쇄망 레지스트리로
'**' 패턴에서 proxy 를 빼고 verdaccio 를 다시 띄운다.
proxy 가 없는 패턴은 로컬 저장소에 있는 것만 내줍니다. 설정은 기동할 때 읽히므로 프로세스를 내리고 다시 띄워야 합니다. 저장소에 없는 패키지를 요청해 404 가 나는지 보세요.
새 캐시로 잠금 파일대로 설치
/root/npm/app2 에 app 의 package.json·package-lock.json·.npmrc 를 복사하고 새 캐시 /root/npm/cache2 로 npm ci 한다.
npm ci 는 잠금 파일이 반드시 있어야 하고 그대로 설치합니다. 캐시 디렉터리를 새로 주면 이전에 받아 둔 것이 도와주지 못하므로, 레지스트리만으로 되는지 시험하는 셈입니다.
바깥 잠금 파일의 주소는 어떻게 풀리나
/root/npm/outlock/ 에 바깥 레지스트리로 chalk 4.1.2 잠금 파일을 만들고, 바깥을 막은 채 사내 레지스트리로 npm ci 를 기본값과 --replace-registry-host=never 로 돌려 /root/npm/lockhost.txt 에 default=·never= 결과(ok 또는 fail)를 적는다.
잠금 파일의 resolved 에 박힌 호스트가 기본 레지스트리일 때 npm 이 무엇을 하는지는 replace-registry-host 설정이 정합니다. 두 번 모두 새 캐시와 새 디렉터리에서, 바깥을 막은 채로 돌려야 공정한 비교입니다. 결과는 명령의 종료 코드로 판단하세요.