mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-02-21 07:29:37 +01:00
add docker examples to use plugins with docker files (#3217)
* add docker examples to use plugins at docker * Update Dockerfile * chore: add v6 examples
This commit is contained in:
parent
6d8aa9817c
commit
aea3b9ddaf
@ -11,3 +11,4 @@ wiki/
|
|||||||
dist/
|
dist/
|
||||||
docs/
|
docs/
|
||||||
test/functional/store/*
|
test/functional/store/*
|
||||||
|
docker-examples/**/lib/**/*.js
|
||||||
|
@ -3,3 +3,12 @@
|
|||||||
> Before run examples, build the local image by running `pnpm docker`.
|
> Before run examples, build the local image by running `pnpm docker`.
|
||||||
|
|
||||||
- [Docker + Nginx + Verdaccio](reverse_proxy/nginx/README.md)
|
- [Docker + Nginx + Verdaccio](reverse_proxy/nginx/README.md)
|
||||||
|
|
||||||
|
## Using Plugins with Docker
|
||||||
|
|
||||||
|
List of different approaches
|
||||||
|
|
||||||
|
> Note these options could be improved, feel free to submit upgrades
|
||||||
|
|
||||||
|
- [Docker + Install plugins from a registry](plugins/docker-build-install-plugin/README.md)
|
||||||
|
- [Docker + Install local plugin](plugins/docker-local-plugin/README.md)
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
# Docs based on https://github.com/xlts-dev/verdaccio-prometheus-middleware#installation
|
||||||
|
|
||||||
|
# Docker multi-stage build - https://docs.docker.com/develop/develop-images/multistage-build/
|
||||||
|
# Use an alpine node image to install the plugin
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
|
||||||
|
# Install the metrics middleware plugin
|
||||||
|
# npm docs
|
||||||
|
# --global-style https://docs.npmjs.com/cli/v7/commands/npm-install#global-style
|
||||||
|
# --no-bin-links https://docs.npmjs.com/cli/v7/commands/npm-install#bin-links
|
||||||
|
# --omit=optional
|
||||||
|
RUN mkdir -p /verdaccio/plugins \
|
||||||
|
&& cd /verdaccio/plugins \
|
||||||
|
&& npm install --global-style --no-bin-links --omit=optional verdaccio-auth-memory@latest
|
||||||
|
|
||||||
|
# The final built image will be based on the standard Verdaccio docker image.
|
||||||
|
FROM verdaccio/verdaccio:5
|
||||||
|
|
||||||
|
# Copy the plugin files over from the 'builder' node image.
|
||||||
|
# The `$VERDACCIO_USER_UID` env variable is defined in the base `verdaccio/verdaccio` image.
|
||||||
|
# Refer to: https://github.com/verdaccio/verdaccio/blob/v5.2.0/Dockerfile#L32
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/node_modules/verdaccio-auth-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-auth-memory
|
@ -0,0 +1,46 @@
|
|||||||
|
# Installing a plugin with Docker build
|
||||||
|
|
||||||
|
On this small tutorial (based on [`verdaccio-prometheus-middleware`](https://github.com/xlts-dev/verdaccio-prometheus-middleware) example) you will be able to use a published package in any random registry (npmjs by default) and use it withing a docker image without mapping need it.
|
||||||
|
|
||||||
|
> Since verdaccio:5 uses `yarn@2` to run the application, this tutorial is a workaround but future prove since verdaccio 6 uses `pnpm` to build the docker image.
|
||||||
|
|
||||||
|
There are two main steps to highlight:
|
||||||
|
|
||||||
|
- `docker.yaml`: This is a copy of the original configuration file for docker and with small modifications to use the plugin [`verdaccio-auth-memory`](https://www.npmjs.com/package/verdaccio-auth-memory) and custom web title for demonstration.
|
||||||
|
- The `Dockerfile` take advance of the docker multi-stage build to install the plugin into the `verdaccio/plugins` folder withing the image, then we apply the right permissions `--chown=$VERDACCIO_USER_UID:root` so the plugin is recognized.
|
||||||
|
|
||||||
|
## Run it
|
||||||
|
|
||||||
|
Build this image.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t verdaccio/verdaccio:local .
|
||||||
|
```
|
||||||
|
|
||||||
|
and to run it
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio:local
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Docker multi-stage build - https://docs.docker.com/develop/develop-images/multistage-build/
|
||||||
|
# Use an alpine node image to install the plugin
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
|
||||||
|
RUN mkdir -p /verdaccio/plugins \
|
||||||
|
&& cd /verdaccio/plugins \
|
||||||
|
&& npm install --global-style --no-bin-links --omit=optional verdaccio-auth-memory@latest
|
||||||
|
|
||||||
|
FROM verdaccio/verdaccio:5
|
||||||
|
|
||||||
|
# copy your modified config.yaml into the image
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/node_modules/verdaccio-auth-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-auth-memory
|
||||||
|
|
||||||
|
```
|
@ -0,0 +1,197 @@
|
|||||||
|
#
|
||||||
|
# This is the default configuration file. It allows all users to do anything,
|
||||||
|
# please read carefully the documentation and best practices to
|
||||||
|
# improve security.
|
||||||
|
#
|
||||||
|
# Do not configure host and port under `listen` in this file
|
||||||
|
# as it will be ignored when using docker.
|
||||||
|
# see https://verdaccio.org/docs/en/docker#docker-and-custom-port-configuration
|
||||||
|
#
|
||||||
|
# Look here for more config file examples:
|
||||||
|
# https://github.com/verdaccio/verdaccio/tree/5.x/conf
|
||||||
|
#
|
||||||
|
# Read about the best practices
|
||||||
|
# https://verdaccio.org/docs/best
|
||||||
|
|
||||||
|
# path to a directory with all packages
|
||||||
|
storage: /verdaccio/storage/data
|
||||||
|
# path to a directory with plugins to include
|
||||||
|
plugins: /verdaccio/plugins
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/webui
|
||||||
|
web:
|
||||||
|
title: Verdaccio Publish Config Test
|
||||||
|
# comment out to disable gravatar support
|
||||||
|
# gravatar: false
|
||||||
|
# by default packages are ordercer ascendant (asc|desc)
|
||||||
|
# sort_packages: asc
|
||||||
|
# convert your UI to the dark side
|
||||||
|
# darkMode: true
|
||||||
|
# html_cache: true
|
||||||
|
# by default all features are displayed
|
||||||
|
# login: true
|
||||||
|
# showInfo: true
|
||||||
|
# showSettings: true
|
||||||
|
# In combination with darkMode you can force specific theme
|
||||||
|
# showThemeSwitch: true
|
||||||
|
# showFooter: true
|
||||||
|
# showSearch: true
|
||||||
|
# showRaw: true
|
||||||
|
# showDownloadTarball: true
|
||||||
|
# HTML tags injected after manifest <scripts/>
|
||||||
|
# scriptsBodyAfter:
|
||||||
|
# - '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
|
||||||
|
# HTML tags injected before ends </head>
|
||||||
|
# metaScripts:
|
||||||
|
# - '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
|
||||||
|
# - '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
|
||||||
|
# - '<meta name="robots" content="noindex" />'
|
||||||
|
# HTML tags injected first child at <body/>
|
||||||
|
# bodyBefore:
|
||||||
|
# - '<div id="myId">html before webpack scripts</div>'
|
||||||
|
# Public path for template manifest scripts (only manifest)
|
||||||
|
# publicPath: http://somedomain.org/
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#authentication
|
||||||
|
auth:
|
||||||
|
auth-memory:
|
||||||
|
users:
|
||||||
|
foo:
|
||||||
|
name: foo
|
||||||
|
password: s3cret
|
||||||
|
bar:
|
||||||
|
name: bar
|
||||||
|
password: s3cret
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#uplinks
|
||||||
|
# a list of other known repositories we can talk to
|
||||||
|
uplinks:
|
||||||
|
npmjs:
|
||||||
|
url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
# Learn how to protect your packages
|
||||||
|
# https://verdaccio.org/docs/protect-your-dependencies/
|
||||||
|
# https://verdaccio.org/docs/configuration#packages
|
||||||
|
packages:
|
||||||
|
'@*/*':
|
||||||
|
# scoped packages
|
||||||
|
access: $all
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
'**':
|
||||||
|
# allow all users (including non-authenticated users) to read and
|
||||||
|
# publish all packages
|
||||||
|
#
|
||||||
|
# you can specify usernames/groupnames (depending on your auth plugin)
|
||||||
|
# and three keywords: "$all", "$anonymous", "$authenticated"
|
||||||
|
access: $all
|
||||||
|
|
||||||
|
# allow all known users to publish/publish packages
|
||||||
|
# (anyone can register by default, remember?)
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
|
||||||
|
# if package is not available locally, proxy requests to 'npmjs' registry
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
# To improve your security configuration and avoid dependency confusion
|
||||||
|
# consider removing the proxy property for private packages
|
||||||
|
# https://verdaccio.org/docs/best#remove-proxy-to-increase-security-at-private-packages
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#server
|
||||||
|
# You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections.
|
||||||
|
# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
|
||||||
|
# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.
|
||||||
|
server:
|
||||||
|
keepAliveTimeout: 60
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#offline-publish
|
||||||
|
# publish:
|
||||||
|
# allow_offline: false
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#url-prefix
|
||||||
|
# url_prefix: /verdaccio/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/my_prefix'
|
||||||
|
# // url -> https://somedomain.org/my_prefix/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/'
|
||||||
|
# // url -> https://somedomain.org/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
|
||||||
|
# url_prefix: '/second_prefix'
|
||||||
|
# // url -> https://somedomain.org/second_prefix/'
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#security
|
||||||
|
# security:
|
||||||
|
# api:
|
||||||
|
# legacy: true
|
||||||
|
# jwt:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 29d
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
# web:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 1h # 1 hour by default
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#user-rate-limit
|
||||||
|
# userRateLimit:
|
||||||
|
# windowMs: 50000
|
||||||
|
# max: 1000
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#max-body-size
|
||||||
|
# max_body_size: 10mb
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#listen-port
|
||||||
|
# listen:
|
||||||
|
# - localhost:4873 # default value
|
||||||
|
# - http://localhost:4873 # same thing
|
||||||
|
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
|
||||||
|
# - https://example.org:4873 # if you want to use https
|
||||||
|
# - "[::1]:4873" # ipv6
|
||||||
|
# - unix:/tmp/verdaccio.sock # unix socket
|
||||||
|
|
||||||
|
# The HTTPS configuration is useful if you do not consider use a HTTP Proxy
|
||||||
|
# https://verdaccio.org/docs/configuration#https
|
||||||
|
# https:
|
||||||
|
# key: ./path/verdaccio-key.pem
|
||||||
|
# cert: ./path/verdaccio-cert.pem
|
||||||
|
# ca: ./path/verdaccio-csr.pem
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#proxy
|
||||||
|
# http_proxy: http://something.local/
|
||||||
|
# https_proxy: https://something.local/
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#notifications
|
||||||
|
# notify:
|
||||||
|
# method: POST
|
||||||
|
# headers: [{ "Content-Type": "application/json" }]
|
||||||
|
# endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||||
|
# content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
||||||
|
|
||||||
|
middlewares:
|
||||||
|
audit:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/logger
|
||||||
|
# log settings
|
||||||
|
logs: { type: stdout, format: pretty, level: http }
|
||||||
|
#experiments:
|
||||||
|
# # support for npm token command
|
||||||
|
# token: false
|
||||||
|
# # enable tarball URL redirect for hosting tarball with a different server, the tarball_url_redirect can be a template string
|
||||||
|
# tarball_url_redirect: 'https://mycdn.com/verdaccio/${packageName}/${filename}'
|
||||||
|
# # the tarball_url_redirect can be a function, takes packageName and filename and returns the url, when working with a js configuration file
|
||||||
|
# tarball_url_redirect(packageName, filename) {
|
||||||
|
# const signedUrl = // generate a signed url
|
||||||
|
# return signedUrl;
|
||||||
|
# }
|
||||||
|
|
||||||
|
# translate your registry, api i18n not available yet
|
||||||
|
# i18n:
|
||||||
|
# list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md
|
||||||
|
# web: en-US
|
26
docker-examples/v5/plugins/docker-local-plugin/Dockerfile
Normal file
26
docker-examples/v5/plugins/docker-local-plugin/Dockerfile
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Docs based on https://github.com/xlts-dev/verdaccio-prometheus-middleware#installation
|
||||||
|
# Docker multi-stage build - https://docs.docker.com/develop/develop-images/multistage-build/
|
||||||
|
# Use an alpine node image to install the plugin
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
|
||||||
|
RUN mkdir -p /verdaccio/plugins
|
||||||
|
|
||||||
|
# Copy the local plugin into the docker image
|
||||||
|
ADD plugins/verdaccio-docker-memory /verdaccio/plugins/verdaccio-docker-memory
|
||||||
|
# Install the production dependencies (be careful install devDependencies here)
|
||||||
|
RUN cd /verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
&& npm install --production
|
||||||
|
|
||||||
|
# The final built image will be based on the standard Verdaccio docker image.
|
||||||
|
FROM verdaccio/verdaccio:5
|
||||||
|
|
||||||
|
# Copy the plugin files over from the 'builder' node image.
|
||||||
|
# The `$VERDACCIO_USER_UID` env variable is defined in the base `verdaccio/verdaccio` image.
|
||||||
|
# Refer to: https://github.com/verdaccio/verdaccio/blob/v5.2.0/Dockerfile#L32
|
||||||
|
# The local verdaccio-docker-memory is setup as storage
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
|
||||||
|
# Copy the plugin into the /verdaccio/plugins
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory
|
42
docker-examples/v5/plugins/docker-local-plugin/README.md
Normal file
42
docker-examples/v5/plugins/docker-local-plugin/README.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Installing a local plugin with Docker build
|
||||||
|
|
||||||
|
On this small tutorial (based on [`verdaccio-prometheus-middleware`](https://github.com/xlts-dev/verdaccio-prometheus-middleware) example) you will be able to use a published package in any random registry (npmjs by default) and use it withing a docker image without mapping need it.
|
||||||
|
|
||||||
|
> Since verdaccio:5 uses `yarn@2` to run the application, this tutorial is a workaround but future prove since verdaccio 6 uses `pnpm` to build the docker image.
|
||||||
|
|
||||||
|
There are three main steps to highlight:
|
||||||
|
|
||||||
|
- Note the custom plugin at `plugins/verdaccio-docker-memory` under the name `verdaccio-docker-memory`.
|
||||||
|
- Install the _production_ dependencies for the plugin `verdaccio-docker-memory`
|
||||||
|
- `docker.yaml`: This is a copy of the original configuration file for docker and with small modifications to use the local plugin `verdaccio-docker-memory`.
|
||||||
|
- The `Dockerfile` take advance of the docker multi-stage build to copy the local plugin into the `verdaccio/plugins` folder withing the image, then we apply the right permissions `--chown=$VERDACCIO_USER_UID:root` so the plugin is recognized.
|
||||||
|
|
||||||
|
## Run it
|
||||||
|
|
||||||
|
Build this image.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t verdaccio/verdaccio:local .
|
||||||
|
```
|
||||||
|
|
||||||
|
and to run it
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio:local
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
RUN mkdir -p /verdaccio/plugins
|
||||||
|
ADD plugins/verdaccio-docker-memory /verdaccio/plugins/verdaccio-docker-memory
|
||||||
|
RUN cd /verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
&& ls -ls \
|
||||||
|
&& npm install --production
|
||||||
|
FROM verdaccio/verdaccio:5
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory
|
||||||
|
```
|
199
docker-examples/v5/plugins/docker-local-plugin/docker.yaml
Normal file
199
docker-examples/v5/plugins/docker-local-plugin/docker.yaml
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
#
|
||||||
|
# This is the default configuration file. It allows all users to do anything,
|
||||||
|
# please read carefully the documentation and best practices to
|
||||||
|
# improve security.
|
||||||
|
#
|
||||||
|
# Do not configure host and port under `listen` in this file
|
||||||
|
# as it will be ignored when using docker.
|
||||||
|
# see https://verdaccio.org/docs/en/docker#docker-and-custom-port-configuration
|
||||||
|
#
|
||||||
|
# Look here for more config file examples:
|
||||||
|
# https://github.com/verdaccio/verdaccio/tree/5.x/conf
|
||||||
|
#
|
||||||
|
# Read about the best practices
|
||||||
|
# https://verdaccio.org/docs/best
|
||||||
|
|
||||||
|
# path to a directory with all packages
|
||||||
|
storage: /verdaccio/storage/data
|
||||||
|
|
||||||
|
store:
|
||||||
|
# dummy copy of https://www.npmjs.com/package/verdaccio-memory
|
||||||
|
docker-memory:
|
||||||
|
limit: 1000
|
||||||
|
|
||||||
|
# path to a directory with plugins to include
|
||||||
|
plugins: /verdaccio/plugins
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/webui
|
||||||
|
web:
|
||||||
|
title: Verdaccio This is a Test
|
||||||
|
# comment out to disable gravatar support
|
||||||
|
# gravatar: false
|
||||||
|
# by default packages are ordercer ascendant (asc|desc)
|
||||||
|
# sort_packages: asc
|
||||||
|
# convert your UI to the dark side
|
||||||
|
# darkMode: true
|
||||||
|
# html_cache: true
|
||||||
|
# by default all features are displayed
|
||||||
|
# login: true
|
||||||
|
# showInfo: true
|
||||||
|
# showSettings: true
|
||||||
|
# In combination with darkMode you can force specific theme
|
||||||
|
# showThemeSwitch: true
|
||||||
|
# showFooter: true
|
||||||
|
# showSearch: true
|
||||||
|
# showRaw: true
|
||||||
|
# showDownloadTarball: true
|
||||||
|
# HTML tags injected after manifest <scripts/>
|
||||||
|
# scriptsBodyAfter:
|
||||||
|
# - '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
|
||||||
|
# HTML tags injected before ends </head>
|
||||||
|
# metaScripts:
|
||||||
|
# - '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
|
||||||
|
# - '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
|
||||||
|
# - '<meta name="robots" content="noindex" />'
|
||||||
|
# HTML tags injected first child at <body/>
|
||||||
|
# bodyBefore:
|
||||||
|
# - '<div id="myId">html before webpack scripts</div>'
|
||||||
|
# Public path for template manifest scripts (only manifest)
|
||||||
|
# publicPath: http://somedomain.org/
|
||||||
|
|
||||||
|
auth:
|
||||||
|
htpasswd:
|
||||||
|
file: ./htpasswd
|
||||||
|
# Maximum amount of users allowed to register, defaults to "+inf".
|
||||||
|
# You can set this to -1 to disable registration.
|
||||||
|
# max_users: 1000
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#uplinks
|
||||||
|
# a list of other known repositories we can talk to
|
||||||
|
uplinks:
|
||||||
|
npmjs:
|
||||||
|
url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
# Learn how to protect your packages
|
||||||
|
# https://verdaccio.org/docs/protect-your-dependencies/
|
||||||
|
# https://verdaccio.org/docs/configuration#packages
|
||||||
|
packages:
|
||||||
|
'@*/*':
|
||||||
|
# scoped packages
|
||||||
|
access: $all
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
'**':
|
||||||
|
# allow all users (including non-authenticated users) to read and
|
||||||
|
# publish all packages
|
||||||
|
#
|
||||||
|
# you can specify usernames/groupnames (depending on your auth plugin)
|
||||||
|
# and three keywords: "$all", "$anonymous", "$authenticated"
|
||||||
|
access: $all
|
||||||
|
|
||||||
|
# allow all known users to publish/publish packages
|
||||||
|
# (anyone can register by default, remember?)
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
|
||||||
|
# if package is not available locally, proxy requests to 'npmjs' registry
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
# To improve your security configuration and avoid dependency confusion
|
||||||
|
# consider removing the proxy property for private packages
|
||||||
|
# https://verdaccio.org/docs/best#remove-proxy-to-increase-security-at-private-packages
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#server
|
||||||
|
# You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections.
|
||||||
|
# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
|
||||||
|
# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.
|
||||||
|
server:
|
||||||
|
keepAliveTimeout: 60
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#offline-publish
|
||||||
|
# publish:
|
||||||
|
# allow_offline: false
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#url-prefix
|
||||||
|
# url_prefix: /verdaccio/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/my_prefix'
|
||||||
|
# // url -> https://somedomain.org/my_prefix/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/'
|
||||||
|
# // url -> https://somedomain.org/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
|
||||||
|
# url_prefix: '/second_prefix'
|
||||||
|
# // url -> https://somedomain.org/second_prefix/'
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#security
|
||||||
|
# security:
|
||||||
|
# api:
|
||||||
|
# legacy: true
|
||||||
|
# jwt:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 29d
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
# web:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 1h # 1 hour by default
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#user-rate-limit
|
||||||
|
# userRateLimit:
|
||||||
|
# windowMs: 50000
|
||||||
|
# max: 1000
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#max-body-size
|
||||||
|
# max_body_size: 10mb
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#listen-port
|
||||||
|
# listen:
|
||||||
|
# - localhost:4873 # default value
|
||||||
|
# - http://localhost:4873 # same thing
|
||||||
|
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
|
||||||
|
# - https://example.org:4873 # if you want to use https
|
||||||
|
# - "[::1]:4873" # ipv6
|
||||||
|
# - unix:/tmp/verdaccio.sock # unix socket
|
||||||
|
|
||||||
|
# The HTTPS configuration is useful if you do not consider use a HTTP Proxy
|
||||||
|
# https://verdaccio.org/docs/configuration#https
|
||||||
|
# https:
|
||||||
|
# key: ./path/verdaccio-key.pem
|
||||||
|
# cert: ./path/verdaccio-cert.pem
|
||||||
|
# ca: ./path/verdaccio-csr.pem
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#proxy
|
||||||
|
# http_proxy: http://something.local/
|
||||||
|
# https_proxy: https://something.local/
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#notifications
|
||||||
|
# notify:
|
||||||
|
# method: POST
|
||||||
|
# headers: [{ "Content-Type": "application/json" }]
|
||||||
|
# endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||||
|
# content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
||||||
|
|
||||||
|
middlewares:
|
||||||
|
audit:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/logger
|
||||||
|
# log settings
|
||||||
|
logs: { type: stdout, format: pretty, level: http }
|
||||||
|
#experiments:
|
||||||
|
# # support for npm token command
|
||||||
|
# token: false
|
||||||
|
# # enable tarball URL redirect for hosting tarball with a different server, the tarball_url_redirect can be a template string
|
||||||
|
# tarball_url_redirect: 'https://mycdn.com/verdaccio/${packageName}/${filename}'
|
||||||
|
# # the tarball_url_redirect can be a function, takes packageName and filename and returns the url, when working with a js configuration file
|
||||||
|
# tarball_url_redirect(packageName, filename) {
|
||||||
|
# const signedUrl = // generate a signed url
|
||||||
|
# return signedUrl;
|
||||||
|
# }
|
||||||
|
|
||||||
|
# translate your registry, api i18n not available yet
|
||||||
|
# i18n:
|
||||||
|
# list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md
|
||||||
|
# web: en-US
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
"max-len": 0,
|
||||||
|
"@typescript-eslint/prefer-optional-chain": 0,
|
||||||
|
"@typescript-eslint/no-unused-vars": 0,
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": 0
|
||||||
|
}
|
||||||
|
}
|
17
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/index.js
Normal file
17
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
exports.LocalMemory = undefined;
|
||||||
|
|
||||||
|
let _localMemory = require('./local-memory');
|
||||||
|
|
||||||
|
let _localMemory2 = _interopRequireDefault(_localMemory);
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) {
|
||||||
|
return obj && obj.__esModule ? obj : { default: obj };
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.LocalMemory = _localMemory2.default;
|
||||||
|
exports.default = _localMemory2.default;
|
96
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/local-memory.js
Normal file
96
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/local-memory.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
let _memoryHandler = require('./memory-handler');
|
||||||
|
|
||||||
|
let _memoryHandler2 = _interopRequireDefault(_memoryHandler);
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) {
|
||||||
|
return obj && obj.__esModule ? obj : { default: obj };
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_LIMIT = 1000;
|
||||||
|
|
||||||
|
class LocalMemory {
|
||||||
|
constructor(config, options) {
|
||||||
|
this.config = config;
|
||||||
|
this.limit = config.limit || DEFAULT_LIMIT;
|
||||||
|
this.logger = options.logger;
|
||||||
|
this.data = this._createEmtpyDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSecret() {
|
||||||
|
return Promise.resolve(this.data.secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSecret(secret) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.data.secret = secret;
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add(name, cb) {
|
||||||
|
const list = this.data.list;
|
||||||
|
|
||||||
|
if (list.length < this.limit) {
|
||||||
|
if (list.indexOf(name) === -1) {
|
||||||
|
list.push(name);
|
||||||
|
}
|
||||||
|
cb(null);
|
||||||
|
} else {
|
||||||
|
this.logger.info(
|
||||||
|
{ limit: this.limit },
|
||||||
|
'Storage memory has reached limit of @{limit} packages'
|
||||||
|
);
|
||||||
|
cb(new Error('Storage memory has reached limit of limit packages'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
search(onPackage, onEnd, validateName) {
|
||||||
|
// TODO: pending to implement
|
||||||
|
onEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(name, cb) {
|
||||||
|
const list = this.data.list;
|
||||||
|
|
||||||
|
const item = list.indexOf(name);
|
||||||
|
|
||||||
|
if (item !== -1) {
|
||||||
|
list.splice(item, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(cb) {
|
||||||
|
cb(null, this.data.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
sync() {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
getPackageStorage(packageInfo) {
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
return new _memoryHandler2.default(packageInfo, this.data.files, this.logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
_createEmtpyDatabase() {
|
||||||
|
const list = [];
|
||||||
|
const files = {};
|
||||||
|
const emptyDatabase = {
|
||||||
|
list,
|
||||||
|
files,
|
||||||
|
secret: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
return emptyDatabase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.default = LocalMemory;
|
182
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/memory-handler.js
Normal file
182
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/memory-handler.js
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
exports.fileExist = exports.noSuchFile = undefined;
|
||||||
|
|
||||||
|
let _httpErrors = require('http-errors');
|
||||||
|
|
||||||
|
let _httpErrors2 = _interopRequireDefault(_httpErrors);
|
||||||
|
|
||||||
|
let _memoryFs = require('memory-fs');
|
||||||
|
|
||||||
|
let _memoryFs2 = _interopRequireDefault(_memoryFs);
|
||||||
|
|
||||||
|
let _streams = require('@verdaccio/streams');
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) {
|
||||||
|
return obj && obj.__esModule ? obj : { default: obj };
|
||||||
|
}
|
||||||
|
|
||||||
|
// $FlowFixMe
|
||||||
|
const noSuchFile = (exports.noSuchFile = 'ENOENT');
|
||||||
|
|
||||||
|
const fileExist = (exports.fileExist = 'EEXISTS');
|
||||||
|
|
||||||
|
const fSError = function fSError(message, code = 404) {
|
||||||
|
const err = (0, _httpErrors2.default)(code, message);
|
||||||
|
// $FlowFixMe
|
||||||
|
err.code = message;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
|
||||||
|
const noPackageFoundError = function noPackageFoundError(message = 'no such package') {
|
||||||
|
const err = (0, _httpErrors2.default)(404, message);
|
||||||
|
// $FlowFixMe
|
||||||
|
err.code = noSuchFile;
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
const fs = new _memoryFs2.default();
|
||||||
|
|
||||||
|
class MemoryHandler {
|
||||||
|
constructor(packageName, data, logger) {
|
||||||
|
// this is not need it
|
||||||
|
this.data = data;
|
||||||
|
this.name = packageName;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePackage(pkgFileName, updateHandler, onWrite, transformPackage, onEnd) {
|
||||||
|
let json = this._getStorage(pkgFileName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
json = JSON.parse(json);
|
||||||
|
} catch (err) {
|
||||||
|
return onEnd(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHandler(json, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return onEnd(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
onWrite(pkgFileName, transformPackage(json), onEnd);
|
||||||
|
} catch (err) {
|
||||||
|
return onEnd(fSError('error on parse', 500));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deletePackage(pkgName, callback) {
|
||||||
|
delete this.data[pkgName];
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
removePackage(callback) {
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
createPackage(name, value, cb) {
|
||||||
|
this.savePackage(name, value, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
savePackage(name, value, cb) {
|
||||||
|
try {
|
||||||
|
const json = JSON.stringify(value, null, '\t');
|
||||||
|
|
||||||
|
this.data[name] = json;
|
||||||
|
} catch (err) {
|
||||||
|
cb(fSError(err.message, 500));
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
readPackage(name, cb) {
|
||||||
|
const json = this._getStorage(name);
|
||||||
|
const isJson = typeof json === 'undefined';
|
||||||
|
|
||||||
|
try {
|
||||||
|
cb(isJson ? noPackageFoundError() : null, JSON.parse(json));
|
||||||
|
} catch (err) {
|
||||||
|
cb(noPackageFoundError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeTarball(name) {
|
||||||
|
const uploadStream = new _streams.UploadTarball();
|
||||||
|
const temporalName = `/${name}`;
|
||||||
|
|
||||||
|
process.nextTick(function () {
|
||||||
|
fs.exists(temporalName, function (exists) {
|
||||||
|
if (exists) {
|
||||||
|
return uploadStream.emit('error', fSError(fileExist));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const file = fs.createWriteStream(temporalName);
|
||||||
|
|
||||||
|
uploadStream.pipe(file);
|
||||||
|
|
||||||
|
uploadStream.done = function () {
|
||||||
|
const onEnd = function onEnd() {
|
||||||
|
uploadStream.emit('success');
|
||||||
|
};
|
||||||
|
|
||||||
|
uploadStream.on('end', onEnd);
|
||||||
|
};
|
||||||
|
|
||||||
|
uploadStream.abort = function () {
|
||||||
|
uploadStream.emit('error', fSError('transmision aborted', 400));
|
||||||
|
file.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
uploadStream.emit('open');
|
||||||
|
} catch (err) {
|
||||||
|
uploadStream.emit('error', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return uploadStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
readTarball(name) {
|
||||||
|
const pathName = `/${name}`;
|
||||||
|
|
||||||
|
const readTarballStream = new _streams.ReadTarball();
|
||||||
|
|
||||||
|
process.nextTick(function () {
|
||||||
|
fs.exists(pathName, function (exists) {
|
||||||
|
if (!exists) {
|
||||||
|
readTarballStream.emit('error', noPackageFoundError());
|
||||||
|
} else {
|
||||||
|
const readStream = fs.createReadStream(pathName);
|
||||||
|
|
||||||
|
readTarballStream.emit('content-length', fs.data[name].length);
|
||||||
|
readTarballStream.emit('open');
|
||||||
|
readStream.pipe(readTarballStream);
|
||||||
|
readStream.on('error', (error) => {
|
||||||
|
readTarballStream.emit('error', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
readTarballStream.abort = function () {
|
||||||
|
readStream.destroy(fSError('read has been aborted', 400));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return readTarballStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getStorage(name = '') {
|
||||||
|
return this.data[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.default = MemoryHandler;
|
19
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/package.json
Normal file
19
docker-examples/v5/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/package.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "verdaccio-docker-memory",
|
||||||
|
"version": "1.0.3",
|
||||||
|
"description": "storage implementation in memory",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"@verdaccio/streams": "1.0.0",
|
||||||
|
"http-errors": "1.6.3",
|
||||||
|
"memory-fs": "0.4.1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"verdaccio",
|
||||||
|
"plugin",
|
||||||
|
"storage"
|
||||||
|
],
|
||||||
|
"author": "Juan Picado <juanpicado19@gmail.com>",
|
||||||
|
"private": true,
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
@ -1,8 +1,22 @@
|
|||||||
# Verdaccio 6
|
# Verdaccio 6 Examples
|
||||||
|
|
||||||
> We recommend to have installed [docker-compose >= 1.29.0](https://github.com/docker/compose/releases/tag/1.29.2)
|
> We recommend to have installed [docker-compose >= 1.29.0](https://github.com/docker/compose/releases/tag/1.29.2)
|
||||||
|
|
||||||
- [Docker + Nginx + Verdaccio](reverse_proxy/nginx/README.md)
|
## Mapping Volumes
|
||||||
- [Docker + Apache + Verdaccio](apache-verdaccio/README.md)
|
|
||||||
- [Docker + Local Storage Volume + Verdaccio](docker-local-storage-volume/README.md)
|
- [Docker + Local Storage Volume + Verdaccio](docker-local-storage-volume/README.md)
|
||||||
- [Docker + HTTPS Portal + Verdaccio](https-portal-example/README.md)
|
|
||||||
|
## Proxy
|
||||||
|
|
||||||
|
- [Docker + Nginx + Verdaccio](proxy/reverse_proxy/nginx/README.md)
|
||||||
|
- [Docker + Apache + Verdaccio](proxy/apache-verdaccio/README.md)
|
||||||
|
- [Docker + HTTPS Portal + Verdaccio](proxy/https-portal-example/README.md)
|
||||||
|
|
||||||
|
> Looking forward more examples with proxies.
|
||||||
|
|
||||||
|
## Plugins
|
||||||
|
|
||||||
|
Using plugins without `docker-compose` mapping volumes, all withing the `Dockerfile`.
|
||||||
|
|
||||||
|
- [Docker + Local Build Auth Plugin (local development)](plugins/docker-build-install-plugin/README.md)
|
||||||
|
- [Docker + Auth Plugin (from a registry)](plugins/docker-local-plugin/README.md)
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
# Docs based on https://github.com/xlts-dev/verdaccio-prometheus-middleware#installation
|
||||||
|
|
||||||
|
# Docker multi-stage build - https://docs.docker.com/develop/develop-images/multistage-build/
|
||||||
|
# Use an alpine node image to install the plugin
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
|
||||||
|
# Install the metrics middleware plugin
|
||||||
|
# npm docs
|
||||||
|
# --global-style https://docs.npmjs.com/cli/v7/commands/npm-install#global-style
|
||||||
|
# --no-bin-links https://docs.npmjs.com/cli/v7/commands/npm-install#bin-links
|
||||||
|
# --omit=optional
|
||||||
|
RUN mkdir -p /verdaccio/plugins \
|
||||||
|
&& cd /verdaccio/plugins \
|
||||||
|
&& npm install --global-style --no-bin-links --omit=optional verdaccio-auth-memory@latest
|
||||||
|
|
||||||
|
# The final built image will be based on the standard Verdaccio docker image.
|
||||||
|
FROM verdaccio/verdaccio:nightly-master
|
||||||
|
|
||||||
|
# Copy the plugin files over from the 'builder' node image.
|
||||||
|
# The `$VERDACCIO_USER_UID` env variable is defined in the base `verdaccio/verdaccio` image.
|
||||||
|
# Refer to: https://github.com/verdaccio/verdaccio/blob/v5.2.0/Dockerfile#L32
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/node_modules/verdaccio-auth-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-auth-memory
|
@ -0,0 +1,46 @@
|
|||||||
|
# Installing a plugin with Docker build
|
||||||
|
|
||||||
|
On this small tutorial (based on [`verdaccio-prometheus-middleware`](https://github.com/xlts-dev/verdaccio-prometheus-middleware) example) you will be able to use a published package in any random registry (npmjs by default) and use it withing a docker image without mapping need it.
|
||||||
|
|
||||||
|
> Since verdaccio:5 uses `yarn@2` to run the application, this tutorial is a workaround but future prove since verdaccio 6 uses `pnpm` to build the docker image.
|
||||||
|
|
||||||
|
There are two main steps to highlight:
|
||||||
|
|
||||||
|
- `docker.yaml`: This is a copy of the original configuration file for docker and with small modifications to use the plugin [`verdaccio-auth-memory`](https://www.npmjs.com/package/verdaccio-auth-memory) and custom web title for demonstration.
|
||||||
|
- The `Dockerfile` take advance of the docker multi-stage build to install the plugin into the `verdaccio/plugins` folder withing the image, then we apply the right permissions `--chown=$VERDACCIO_USER_UID:root` so the plugin is recognized.
|
||||||
|
|
||||||
|
## Run it
|
||||||
|
|
||||||
|
Build this image.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t verdaccio/verdaccio:local .
|
||||||
|
```
|
||||||
|
|
||||||
|
and to run it
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio:local
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Docker multi-stage build - https://docs.docker.com/develop/develop-images/multistage-build/
|
||||||
|
# Use an alpine node image to install the plugin
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
|
||||||
|
RUN mkdir -p /verdaccio/plugins \
|
||||||
|
&& cd /verdaccio/plugins \
|
||||||
|
&& npm install --global-style --no-bin-links --omit=optional verdaccio-auth-memory@latest
|
||||||
|
|
||||||
|
FROM verdaccio/verdaccio:5
|
||||||
|
|
||||||
|
# copy your modified config.yaml into the image
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/node_modules/verdaccio-auth-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-auth-memory
|
||||||
|
|
||||||
|
```
|
@ -0,0 +1,197 @@
|
|||||||
|
#
|
||||||
|
# This is the default configuration file. It allows all users to do anything,
|
||||||
|
# please read carefully the documentation and best practices to
|
||||||
|
# improve security.
|
||||||
|
#
|
||||||
|
# Do not configure host and port under `listen` in this file
|
||||||
|
# as it will be ignored when using docker.
|
||||||
|
# see https://verdaccio.org/docs/en/docker#docker-and-custom-port-configuration
|
||||||
|
#
|
||||||
|
# Look here for more config file examples:
|
||||||
|
# https://github.com/verdaccio/verdaccio/tree/5.x/conf
|
||||||
|
#
|
||||||
|
# Read about the best practices
|
||||||
|
# https://verdaccio.org/docs/best
|
||||||
|
|
||||||
|
# path to a directory with all packages
|
||||||
|
storage: /verdaccio/storage/data
|
||||||
|
# path to a directory with plugins to include
|
||||||
|
plugins: /verdaccio/plugins
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/webui
|
||||||
|
web:
|
||||||
|
title: Verdaccio Publish Config Test
|
||||||
|
# comment out to disable gravatar support
|
||||||
|
# gravatar: false
|
||||||
|
# by default packages are ordercer ascendant (asc|desc)
|
||||||
|
# sort_packages: asc
|
||||||
|
# convert your UI to the dark side
|
||||||
|
# darkMode: true
|
||||||
|
# html_cache: true
|
||||||
|
# by default all features are displayed
|
||||||
|
# login: true
|
||||||
|
# showInfo: true
|
||||||
|
# showSettings: true
|
||||||
|
# In combination with darkMode you can force specific theme
|
||||||
|
# showThemeSwitch: true
|
||||||
|
# showFooter: true
|
||||||
|
# showSearch: true
|
||||||
|
# showRaw: true
|
||||||
|
# showDownloadTarball: true
|
||||||
|
# HTML tags injected after manifest <scripts/>
|
||||||
|
# scriptsBodyAfter:
|
||||||
|
# - '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
|
||||||
|
# HTML tags injected before ends </head>
|
||||||
|
# metaScripts:
|
||||||
|
# - '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
|
||||||
|
# - '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
|
||||||
|
# - '<meta name="robots" content="noindex" />'
|
||||||
|
# HTML tags injected first child at <body/>
|
||||||
|
# bodyBefore:
|
||||||
|
# - '<div id="myId">html before webpack scripts</div>'
|
||||||
|
# Public path for template manifest scripts (only manifest)
|
||||||
|
# publicPath: http://somedomain.org/
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#authentication
|
||||||
|
auth:
|
||||||
|
auth-memory:
|
||||||
|
users:
|
||||||
|
foo:
|
||||||
|
name: foo
|
||||||
|
password: s3cret
|
||||||
|
bar:
|
||||||
|
name: bar
|
||||||
|
password: s3cret
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#uplinks
|
||||||
|
# a list of other known repositories we can talk to
|
||||||
|
uplinks:
|
||||||
|
npmjs:
|
||||||
|
url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
# Learn how to protect your packages
|
||||||
|
# https://verdaccio.org/docs/protect-your-dependencies/
|
||||||
|
# https://verdaccio.org/docs/configuration#packages
|
||||||
|
packages:
|
||||||
|
'@*/*':
|
||||||
|
# scoped packages
|
||||||
|
access: $all
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
'**':
|
||||||
|
# allow all users (including non-authenticated users) to read and
|
||||||
|
# publish all packages
|
||||||
|
#
|
||||||
|
# you can specify usernames/groupnames (depending on your auth plugin)
|
||||||
|
# and three keywords: "$all", "$anonymous", "$authenticated"
|
||||||
|
access: $all
|
||||||
|
|
||||||
|
# allow all known users to publish/publish packages
|
||||||
|
# (anyone can register by default, remember?)
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
|
||||||
|
# if package is not available locally, proxy requests to 'npmjs' registry
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
# To improve your security configuration and avoid dependency confusion
|
||||||
|
# consider removing the proxy property for private packages
|
||||||
|
# https://verdaccio.org/docs/best#remove-proxy-to-increase-security-at-private-packages
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#server
|
||||||
|
# You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections.
|
||||||
|
# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
|
||||||
|
# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.
|
||||||
|
server:
|
||||||
|
keepAliveTimeout: 60
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#offline-publish
|
||||||
|
# publish:
|
||||||
|
# allow_offline: false
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#url-prefix
|
||||||
|
# url_prefix: /verdaccio/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/my_prefix'
|
||||||
|
# // url -> https://somedomain.org/my_prefix/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/'
|
||||||
|
# // url -> https://somedomain.org/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
|
||||||
|
# url_prefix: '/second_prefix'
|
||||||
|
# // url -> https://somedomain.org/second_prefix/'
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#security
|
||||||
|
# security:
|
||||||
|
# api:
|
||||||
|
# legacy: true
|
||||||
|
# jwt:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 29d
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
# web:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 1h # 1 hour by default
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#user-rate-limit
|
||||||
|
# userRateLimit:
|
||||||
|
# windowMs: 50000
|
||||||
|
# max: 1000
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#max-body-size
|
||||||
|
# max_body_size: 10mb
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#listen-port
|
||||||
|
# listen:
|
||||||
|
# - localhost:4873 # default value
|
||||||
|
# - http://localhost:4873 # same thing
|
||||||
|
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
|
||||||
|
# - https://example.org:4873 # if you want to use https
|
||||||
|
# - "[::1]:4873" # ipv6
|
||||||
|
# - unix:/tmp/verdaccio.sock # unix socket
|
||||||
|
|
||||||
|
# The HTTPS configuration is useful if you do not consider use a HTTP Proxy
|
||||||
|
# https://verdaccio.org/docs/configuration#https
|
||||||
|
# https:
|
||||||
|
# key: ./path/verdaccio-key.pem
|
||||||
|
# cert: ./path/verdaccio-cert.pem
|
||||||
|
# ca: ./path/verdaccio-csr.pem
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#proxy
|
||||||
|
# http_proxy: http://something.local/
|
||||||
|
# https_proxy: https://something.local/
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#notifications
|
||||||
|
# notify:
|
||||||
|
# method: POST
|
||||||
|
# headers: [{ "Content-Type": "application/json" }]
|
||||||
|
# endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||||
|
# content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
||||||
|
|
||||||
|
middlewares:
|
||||||
|
audit:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/logger
|
||||||
|
# log settings
|
||||||
|
logs: { type: stdout, format: pretty, level: http }
|
||||||
|
#experiments:
|
||||||
|
# # support for npm token command
|
||||||
|
# token: false
|
||||||
|
# # enable tarball URL redirect for hosting tarball with a different server, the tarball_url_redirect can be a template string
|
||||||
|
# tarball_url_redirect: 'https://mycdn.com/verdaccio/${packageName}/${filename}'
|
||||||
|
# # the tarball_url_redirect can be a function, takes packageName and filename and returns the url, when working with a js configuration file
|
||||||
|
# tarball_url_redirect(packageName, filename) {
|
||||||
|
# const signedUrl = // generate a signed url
|
||||||
|
# return signedUrl;
|
||||||
|
# }
|
||||||
|
|
||||||
|
# translate your registry, api i18n not available yet
|
||||||
|
# i18n:
|
||||||
|
# list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md
|
||||||
|
# web: en-US
|
26
docker-examples/v6/plugins/docker-local-plugin/Dockerfile
Normal file
26
docker-examples/v6/plugins/docker-local-plugin/Dockerfile
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Docs based on https://github.com/xlts-dev/verdaccio-prometheus-middleware#installation
|
||||||
|
# Docker multi-stage build - https://docs.docker.com/develop/develop-images/multistage-build/
|
||||||
|
# Use an alpine node image to install the plugin
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
|
||||||
|
RUN mkdir -p /verdaccio/plugins
|
||||||
|
|
||||||
|
# Copy the local plugin into the docker image
|
||||||
|
ADD plugins/verdaccio-docker-memory /verdaccio/plugins/verdaccio-docker-memory
|
||||||
|
# Install the production dependencies (be careful install devDependencies here)
|
||||||
|
RUN cd /verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
&& npm install --production
|
||||||
|
|
||||||
|
# The final built image will be based on the standard Verdaccio docker image.
|
||||||
|
FROM verdaccio/verdaccio:nightly-master
|
||||||
|
|
||||||
|
# Copy the plugin files over from the 'builder' node image.
|
||||||
|
# The `$VERDACCIO_USER_UID` env variable is defined in the base `verdaccio/verdaccio` image.
|
||||||
|
# Refer to: https://github.com/verdaccio/verdaccio/blob/v5.2.0/Dockerfile#L32
|
||||||
|
# The local verdaccio-docker-memory is setup as storage
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
|
||||||
|
# Copy the plugin into the /verdaccio/plugins
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory
|
42
docker-examples/v6/plugins/docker-local-plugin/README.md
Normal file
42
docker-examples/v6/plugins/docker-local-plugin/README.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Installing a local plugin with Docker build
|
||||||
|
|
||||||
|
On this small tutorial (based on [`verdaccio-prometheus-middleware`](https://github.com/xlts-dev/verdaccio-prometheus-middleware) example) you will be able to use a published package in any random registry (npmjs by default) and use it withing a docker image without mapping need it.
|
||||||
|
|
||||||
|
> Since verdaccio:5 uses `yarn@2` to run the application, this tutorial is a workaround but future prove since verdaccio 6 uses `pnpm` to build the docker image.
|
||||||
|
|
||||||
|
There are three main steps to highlight:
|
||||||
|
|
||||||
|
- Note the custom plugin at `plugins/verdaccio-docker-memory` under the name `verdaccio-docker-memory`.
|
||||||
|
- Install the _production_ dependencies for the plugin `verdaccio-docker-memory`
|
||||||
|
- `docker.yaml`: This is a copy of the original configuration file for docker and with small modifications to use the local plugin `verdaccio-docker-memory`.
|
||||||
|
- The `Dockerfile` take advance of the docker multi-stage build to copy the local plugin into the `verdaccio/plugins` folder withing the image, then we apply the right permissions `--chown=$VERDACCIO_USER_UID:root` so the plugin is recognized.
|
||||||
|
|
||||||
|
## Run it
|
||||||
|
|
||||||
|
Build this image.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t verdaccio/verdaccio:local .
|
||||||
|
```
|
||||||
|
|
||||||
|
and to run it
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio:local
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM node:lts-alpine as builder
|
||||||
|
RUN mkdir -p /verdaccio/plugins
|
||||||
|
ADD plugins/verdaccio-docker-memory /verdaccio/plugins/verdaccio-docker-memory
|
||||||
|
RUN cd /verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
&& ls -ls \
|
||||||
|
&& npm install --production
|
||||||
|
FROM verdaccio/verdaccio:5
|
||||||
|
ADD docker.yaml /verdaccio/conf/config.yaml
|
||||||
|
COPY --chown=$VERDACCIO_USER_UID:root --from=builder \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory \
|
||||||
|
/verdaccio/plugins/verdaccio-docker-memory
|
||||||
|
```
|
199
docker-examples/v6/plugins/docker-local-plugin/docker.yaml
Normal file
199
docker-examples/v6/plugins/docker-local-plugin/docker.yaml
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
#
|
||||||
|
# This is the default configuration file. It allows all users to do anything,
|
||||||
|
# please read carefully the documentation and best practices to
|
||||||
|
# improve security.
|
||||||
|
#
|
||||||
|
# Do not configure host and port under `listen` in this file
|
||||||
|
# as it will be ignored when using docker.
|
||||||
|
# see https://verdaccio.org/docs/en/docker#docker-and-custom-port-configuration
|
||||||
|
#
|
||||||
|
# Look here for more config file examples:
|
||||||
|
# https://github.com/verdaccio/verdaccio/tree/5.x/conf
|
||||||
|
#
|
||||||
|
# Read about the best practices
|
||||||
|
# https://verdaccio.org/docs/best
|
||||||
|
|
||||||
|
# path to a directory with all packages
|
||||||
|
storage: /verdaccio/storage/data
|
||||||
|
|
||||||
|
store:
|
||||||
|
# dummy copy of https://www.npmjs.com/package/verdaccio-memory
|
||||||
|
docker-memory:
|
||||||
|
limit: 1000
|
||||||
|
|
||||||
|
# path to a directory with plugins to include
|
||||||
|
plugins: /verdaccio/plugins
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/webui
|
||||||
|
web:
|
||||||
|
title: Verdaccio This is a Test
|
||||||
|
# comment out to disable gravatar support
|
||||||
|
# gravatar: false
|
||||||
|
# by default packages are ordercer ascendant (asc|desc)
|
||||||
|
# sort_packages: asc
|
||||||
|
# convert your UI to the dark side
|
||||||
|
# darkMode: true
|
||||||
|
# html_cache: true
|
||||||
|
# by default all features are displayed
|
||||||
|
# login: true
|
||||||
|
# showInfo: true
|
||||||
|
# showSettings: true
|
||||||
|
# In combination with darkMode you can force specific theme
|
||||||
|
# showThemeSwitch: true
|
||||||
|
# showFooter: true
|
||||||
|
# showSearch: true
|
||||||
|
# showRaw: true
|
||||||
|
# showDownloadTarball: true
|
||||||
|
# HTML tags injected after manifest <scripts/>
|
||||||
|
# scriptsBodyAfter:
|
||||||
|
# - '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
|
||||||
|
# HTML tags injected before ends </head>
|
||||||
|
# metaScripts:
|
||||||
|
# - '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
|
||||||
|
# - '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
|
||||||
|
# - '<meta name="robots" content="noindex" />'
|
||||||
|
# HTML tags injected first child at <body/>
|
||||||
|
# bodyBefore:
|
||||||
|
# - '<div id="myId">html before webpack scripts</div>'
|
||||||
|
# Public path for template manifest scripts (only manifest)
|
||||||
|
# publicPath: http://somedomain.org/
|
||||||
|
|
||||||
|
auth:
|
||||||
|
htpasswd:
|
||||||
|
file: ./htpasswd
|
||||||
|
# Maximum amount of users allowed to register, defaults to "+inf".
|
||||||
|
# You can set this to -1 to disable registration.
|
||||||
|
# max_users: 1000
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#uplinks
|
||||||
|
# a list of other known repositories we can talk to
|
||||||
|
uplinks:
|
||||||
|
npmjs:
|
||||||
|
url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
# Learn how to protect your packages
|
||||||
|
# https://verdaccio.org/docs/protect-your-dependencies/
|
||||||
|
# https://verdaccio.org/docs/configuration#packages
|
||||||
|
packages:
|
||||||
|
'@*/*':
|
||||||
|
# scoped packages
|
||||||
|
access: $all
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
'**':
|
||||||
|
# allow all users (including non-authenticated users) to read and
|
||||||
|
# publish all packages
|
||||||
|
#
|
||||||
|
# you can specify usernames/groupnames (depending on your auth plugin)
|
||||||
|
# and three keywords: "$all", "$anonymous", "$authenticated"
|
||||||
|
access: $all
|
||||||
|
|
||||||
|
# allow all known users to publish/publish packages
|
||||||
|
# (anyone can register by default, remember?)
|
||||||
|
publish: $authenticated
|
||||||
|
unpublish: $authenticated
|
||||||
|
|
||||||
|
# if package is not available locally, proxy requests to 'npmjs' registry
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
# To improve your security configuration and avoid dependency confusion
|
||||||
|
# consider removing the proxy property for private packages
|
||||||
|
# https://verdaccio.org/docs/best#remove-proxy-to-increase-security-at-private-packages
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#server
|
||||||
|
# You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections.
|
||||||
|
# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
|
||||||
|
# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.
|
||||||
|
server:
|
||||||
|
keepAliveTimeout: 60
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#offline-publish
|
||||||
|
# publish:
|
||||||
|
# allow_offline: false
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#url-prefix
|
||||||
|
# url_prefix: /verdaccio/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/my_prefix'
|
||||||
|
# // url -> https://somedomain.org/my_prefix/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
|
||||||
|
# url_prefix: '/'
|
||||||
|
# // url -> https://somedomain.org/
|
||||||
|
# VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
|
||||||
|
# url_prefix: '/second_prefix'
|
||||||
|
# // url -> https://somedomain.org/second_prefix/'
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#security
|
||||||
|
# security:
|
||||||
|
# api:
|
||||||
|
# legacy: true
|
||||||
|
# jwt:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 29d
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
# web:
|
||||||
|
# sign:
|
||||||
|
# expiresIn: 1h # 1 hour by default
|
||||||
|
# verify:
|
||||||
|
# someProp: [value]
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#user-rate-limit
|
||||||
|
# userRateLimit:
|
||||||
|
# windowMs: 50000
|
||||||
|
# max: 1000
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#max-body-size
|
||||||
|
# max_body_size: 10mb
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#listen-port
|
||||||
|
# listen:
|
||||||
|
# - localhost:4873 # default value
|
||||||
|
# - http://localhost:4873 # same thing
|
||||||
|
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
|
||||||
|
# - https://example.org:4873 # if you want to use https
|
||||||
|
# - "[::1]:4873" # ipv6
|
||||||
|
# - unix:/tmp/verdaccio.sock # unix socket
|
||||||
|
|
||||||
|
# The HTTPS configuration is useful if you do not consider use a HTTP Proxy
|
||||||
|
# https://verdaccio.org/docs/configuration#https
|
||||||
|
# https:
|
||||||
|
# key: ./path/verdaccio-key.pem
|
||||||
|
# cert: ./path/verdaccio-cert.pem
|
||||||
|
# ca: ./path/verdaccio-csr.pem
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#proxy
|
||||||
|
# http_proxy: http://something.local/
|
||||||
|
# https_proxy: https://something.local/
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/configuration#notifications
|
||||||
|
# notify:
|
||||||
|
# method: POST
|
||||||
|
# headers: [{ "Content-Type": "application/json" }]
|
||||||
|
# endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||||
|
# content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
||||||
|
|
||||||
|
middlewares:
|
||||||
|
audit:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# https://verdaccio.org/docs/logger
|
||||||
|
# log settings
|
||||||
|
log: { type: stdout, format: pretty, level: http }
|
||||||
|
#experiments:
|
||||||
|
# # support for npm token command
|
||||||
|
# token: false
|
||||||
|
# # enable tarball URL redirect for hosting tarball with a different server, the tarball_url_redirect can be a template string
|
||||||
|
# tarball_url_redirect: 'https://mycdn.com/verdaccio/${packageName}/${filename}'
|
||||||
|
# # the tarball_url_redirect can be a function, takes packageName and filename and returns the url, when working with a js configuration file
|
||||||
|
# tarball_url_redirect(packageName, filename) {
|
||||||
|
# const signedUrl = // generate a signed url
|
||||||
|
# return signedUrl;
|
||||||
|
# }
|
||||||
|
|
||||||
|
# translate your registry, api i18n not available yet
|
||||||
|
# i18n:
|
||||||
|
# list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md
|
||||||
|
# web: en-US
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
"max-len": 0,
|
||||||
|
"@typescript-eslint/prefer-optional-chain": 0,
|
||||||
|
"@typescript-eslint/no-unused-vars": 0,
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": 0
|
||||||
|
}
|
||||||
|
}
|
22
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/index.js
Normal file
22
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/index.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, 'LocalMemory', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _localMemory.default;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
exports.default = void 0;
|
||||||
|
|
||||||
|
var _localMemory = _interopRequireDefault(require('./local-memory'));
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) {
|
||||||
|
return obj && obj.__esModule ? obj : { default: obj };
|
||||||
|
}
|
||||||
|
|
||||||
|
var _default = _localMemory.default;
|
||||||
|
exports.default = _default;
|
||||||
|
//# sourceMappingURL=index.js.map
|
141
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/local-memory.js
Normal file
141
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/local-memory.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
exports.default = void 0;
|
||||||
|
|
||||||
|
var _debug = _interopRequireDefault(require('debug'));
|
||||||
|
|
||||||
|
var _core = require('@verdaccio/core');
|
||||||
|
|
||||||
|
var _memoryHandler = _interopRequireDefault(require('./memory-handler'));
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) {
|
||||||
|
return obj && obj.__esModule ? obj : { default: obj };
|
||||||
|
}
|
||||||
|
|
||||||
|
const debug = (0, _debug.default)('verdaccio:plugin:storage:local-memory');
|
||||||
|
const DEFAULT_LIMIT = 1000;
|
||||||
|
|
||||||
|
class LocalMemory {
|
||||||
|
constructor(config, options) {
|
||||||
|
this.config = config;
|
||||||
|
this.limit = config.limit || DEFAULT_LIMIT;
|
||||||
|
this.logger = options.logger;
|
||||||
|
this.data = this._createEmtpyDatabase();
|
||||||
|
this.path = '/';
|
||||||
|
debug('start plugin');
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSecret() {
|
||||||
|
return Promise.resolve(this.data.secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSecret(secret) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.data.secret = secret;
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(name) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const { list } = this.data;
|
||||||
|
|
||||||
|
if (list.length < this.limit) {
|
||||||
|
if (list.indexOf(name) === -1) {
|
||||||
|
list.push(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
this.logger.info(
|
||||||
|
{
|
||||||
|
limit: this.limit,
|
||||||
|
},
|
||||||
|
'Storage memory has reached limit of @{limit} packages'
|
||||||
|
);
|
||||||
|
reject(new Error('Storage memory has reached limit of limit packages'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
|
||||||
|
search(onPackage, onEnd) {
|
||||||
|
this.logger.warn('[verdaccio/memory]: search method not implemented, PR is welcome');
|
||||||
|
onEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(name) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const { list } = this.data;
|
||||||
|
const item = list.indexOf(name);
|
||||||
|
|
||||||
|
if (item !== -1) {
|
||||||
|
list.splice(item, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async get() {
|
||||||
|
var _this$data, _this$data$list, _this$data2;
|
||||||
|
|
||||||
|
debug(
|
||||||
|
'data list length %o',
|
||||||
|
(_this$data = this.data) === null || _this$data === void 0
|
||||||
|
? void 0
|
||||||
|
: (_this$data$list = _this$data.list) === null || _this$data$list === void 0
|
||||||
|
? void 0
|
||||||
|
: _this$data$list.length
|
||||||
|
);
|
||||||
|
return Promise.resolve(
|
||||||
|
(_this$data2 = this.data) === null || _this$data2 === void 0 ? void 0 : _this$data2.list
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPackageStorage(packageInfo) {
|
||||||
|
return new _memoryHandler.default(packageInfo, this.data.files, this.logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
_createEmtpyDatabase() {
|
||||||
|
const list = [];
|
||||||
|
const files = {};
|
||||||
|
const emptyDatabase = {
|
||||||
|
list,
|
||||||
|
files,
|
||||||
|
secret: '',
|
||||||
|
};
|
||||||
|
return emptyDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveToken() {
|
||||||
|
this.logger.warn('[verdaccio/memory][saveToken] save token has not been implemented yet');
|
||||||
|
return Promise.reject(_core.errorUtils.getServiceUnavailable('method not implemented'));
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteToken(user, tokenKey) {
|
||||||
|
this.logger.warn(
|
||||||
|
{
|
||||||
|
tokenKey,
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
'[verdaccio/memory][deleteToken] delete token has not been implemented yet @{user}'
|
||||||
|
);
|
||||||
|
return Promise.reject(_core.errorUtils.getServiceUnavailable('method not implemented'));
|
||||||
|
}
|
||||||
|
|
||||||
|
readTokens() {
|
||||||
|
this.logger.warn('[verdaccio/memory][readTokens] read tokens has not been implemented yet ');
|
||||||
|
return Promise.reject(_core.errorUtils.getServiceUnavailable('method not implemented'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _default = LocalMemory;
|
||||||
|
exports.default = _default;
|
||||||
|
//# sourceMappingURL=local-memory.js.map
|
214
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/memory-handler.js
Normal file
214
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/memory-handler.js
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
exports.default = void 0;
|
||||||
|
|
||||||
|
var _debug = _interopRequireDefault(require('debug'));
|
||||||
|
|
||||||
|
var _memfs = require('memfs');
|
||||||
|
|
||||||
|
var _path = _interopRequireDefault(require('path'));
|
||||||
|
|
||||||
|
var _core = require('@verdaccio/core');
|
||||||
|
|
||||||
|
var _streams = require('@verdaccio/streams');
|
||||||
|
|
||||||
|
var _utils = require('./utils');
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) {
|
||||||
|
return obj && obj.__esModule ? obj : { default: obj };
|
||||||
|
}
|
||||||
|
|
||||||
|
const debug = (0, _debug.default)('verdaccio:plugin:storage:memory-storage');
|
||||||
|
|
||||||
|
class MemoryHandler {
|
||||||
|
constructor(packageName, data, logger) {
|
||||||
|
// this is not need it
|
||||||
|
this.data = data;
|
||||||
|
this.name = packageName;
|
||||||
|
this.logger = logger;
|
||||||
|
this.path = `/${packageName}`;
|
||||||
|
debug('initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePackage(pkgFileName, updateHandler, onWrite, transformPackage, onEnd) {
|
||||||
|
const json = this._getStorage(pkgFileName);
|
||||||
|
|
||||||
|
let pkg;
|
||||||
|
|
||||||
|
try {
|
||||||
|
pkg = (0, _utils.parsePackage)(json);
|
||||||
|
} catch (err) {
|
||||||
|
return onEnd(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHandler(pkg, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return onEnd(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
onWrite(pkgFileName, transformPackage(pkg), onEnd);
|
||||||
|
} catch (err) {
|
||||||
|
return onEnd(_core.errorUtils.getInternalError('error on parse the metadata'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deletePackage(pkgName) {
|
||||||
|
delete this.data[pkgName];
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
removePackage() {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
createPackage(name, value, cb) {
|
||||||
|
debug('create package %o', name);
|
||||||
|
this.savePackage(name, value, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
savePackage(name, value, cb) {
|
||||||
|
try {
|
||||||
|
debug('save package %o', name);
|
||||||
|
this.data[name] = (0, _utils.stringifyPackage)(value);
|
||||||
|
return cb(null);
|
||||||
|
} catch (err) {
|
||||||
|
return cb(_core.errorUtils.getInternalError(err.message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async readPackageNext(name) {
|
||||||
|
const json = this._getStorage(name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (
|
||||||
|
typeof json === 'undefined' ? _core.errorUtils.getNotFound() : null,
|
||||||
|
(0, _utils.parsePackage)(json)
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
throw _core.errorUtils.getNotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readPackage(name, cb) {
|
||||||
|
debug('read package %o', name);
|
||||||
|
|
||||||
|
const json = this._getStorage(name);
|
||||||
|
|
||||||
|
const isJson = typeof json === 'undefined';
|
||||||
|
|
||||||
|
try {
|
||||||
|
return cb(isJson ? _core.errorUtils.getNotFound() : null, (0, _utils.parsePackage)(json));
|
||||||
|
} catch (err) {
|
||||||
|
return cb(_core.errorUtils.getNotFound());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeTarball(name) {
|
||||||
|
const uploadStream = new _streams.UploadTarball({});
|
||||||
|
const temporalName = `${this.path}/${name}`;
|
||||||
|
debug('write tarball %o', temporalName);
|
||||||
|
process.nextTick(function () {
|
||||||
|
_memfs.fs.mkdirp(_path.default.dirname(temporalName), (mkdirpError) => {
|
||||||
|
if (mkdirpError) {
|
||||||
|
return uploadStream.emit('error', mkdirpError);
|
||||||
|
}
|
||||||
|
|
||||||
|
_memfs.fs.stat(temporalName, function (fileError, stats) {
|
||||||
|
if (!fileError && stats) {
|
||||||
|
return uploadStream.emit('error', _core.errorUtils.getConflict());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const file = _memfs.fs.createWriteStream(temporalName);
|
||||||
|
|
||||||
|
uploadStream.pipe(file);
|
||||||
|
|
||||||
|
uploadStream.done = function () {
|
||||||
|
const onEnd = function () {
|
||||||
|
uploadStream.emit('success');
|
||||||
|
};
|
||||||
|
|
||||||
|
uploadStream.on('end', onEnd);
|
||||||
|
};
|
||||||
|
|
||||||
|
uploadStream.abort = function () {
|
||||||
|
uploadStream.emit('error', _core.errorUtils.getBadRequest('transmision aborted'));
|
||||||
|
file.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
uploadStream.emit('open');
|
||||||
|
return;
|
||||||
|
} catch (err) {
|
||||||
|
uploadStream.emit('error', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return uploadStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
readTarball(name) {
|
||||||
|
const pathName = `${this.path}/${name}`;
|
||||||
|
debug('read tarball %o', pathName);
|
||||||
|
const readTarballStream = new _streams.ReadTarball({});
|
||||||
|
process.nextTick(function () {
|
||||||
|
_memfs.fs.stat(pathName, function (error, stats) {
|
||||||
|
if (error && !stats) {
|
||||||
|
return readTarballStream.emit('error', _core.errorUtils.getNotFound());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const readStream = _memfs.fs.createReadStream(pathName);
|
||||||
|
|
||||||
|
readTarballStream.emit(
|
||||||
|
'content-length',
|
||||||
|
stats === null || stats === void 0 ? void 0 : stats.size
|
||||||
|
);
|
||||||
|
readTarballStream.emit('open');
|
||||||
|
readStream.pipe(readTarballStream);
|
||||||
|
readStream.on('error', (error) => {
|
||||||
|
readTarballStream.emit('error', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
readTarballStream.abort = function () {
|
||||||
|
readStream.destroy(_core.errorUtils.getBadRequest('read has been aborted'));
|
||||||
|
};
|
||||||
|
|
||||||
|
return;
|
||||||
|
} catch (err) {
|
||||||
|
readTarballStream.emit('error', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return readTarballStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getStorage(name = '') {
|
||||||
|
debug('get storage %o', name);
|
||||||
|
return this.data[name];
|
||||||
|
} // migration pending
|
||||||
|
|
||||||
|
async updatePackageNext(packageName, handleUpdate) {
|
||||||
|
debug(packageName); // @ts-expect-error
|
||||||
|
|
||||||
|
await handleUpdate({}); // @ts-expect-error
|
||||||
|
|
||||||
|
return Promise.resolve({});
|
||||||
|
}
|
||||||
|
|
||||||
|
async savePackageNext(name, value) {
|
||||||
|
debug(name);
|
||||||
|
debug(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _default = MemoryHandler;
|
||||||
|
exports.default = _default;
|
||||||
|
//# sourceMappingURL=memory-handler.js.map
|
16
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/utils.js
Normal file
16
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/lib/utils.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
exports.parsePackage = parsePackage;
|
||||||
|
exports.stringifyPackage = stringifyPackage;
|
||||||
|
|
||||||
|
function stringifyPackage(pkg) {
|
||||||
|
return JSON.stringify(pkg, null, '\t');
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePackage(pkg) {
|
||||||
|
return JSON.parse(pkg);
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=utils.js.map
|
56
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/package.json
Normal file
56
docker-examples/v6/plugins/docker-local-plugin/plugins/verdaccio-docker-memory/package.json
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"name": "verdaccio-docker-memory",
|
||||||
|
"version": "11.0.0-6-next.10",
|
||||||
|
"description": "Storage implementation in memory",
|
||||||
|
"keywords": [
|
||||||
|
"private",
|
||||||
|
"package",
|
||||||
|
"repository",
|
||||||
|
"registry",
|
||||||
|
"enterprise",
|
||||||
|
"modules",
|
||||||
|
"proxy",
|
||||||
|
"server",
|
||||||
|
"verdaccio"
|
||||||
|
],
|
||||||
|
"author": "Juan Picado <juanpicado19@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://verdaccio.org",
|
||||||
|
"repository": {
|
||||||
|
"type": "https",
|
||||||
|
"url": "https://github.com/verdaccio/verdaccio",
|
||||||
|
"directory": "packages/plugins/memory"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/verdaccio/verdaccio/issues"
|
||||||
|
},
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"types": "lib/index.d.ts",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@verdaccio/core": "6.0.0-6-next.5",
|
||||||
|
"@verdaccio/streams": "11.0.0-6-next.5",
|
||||||
|
"memory-fs": "0.5.0",
|
||||||
|
"debug": "4.3.3",
|
||||||
|
"memfs": "3.4.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@verdaccio/types": "11.0.0-6-next.12"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rimraf ./build",
|
||||||
|
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
||||||
|
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
|
||||||
|
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
||||||
|
"build": "pnpm run build:js && pnpm run build:types",
|
||||||
|
"watch": "pnpm build:js -- --watch",
|
||||||
|
"test": "cross-env NODE_ENV=test BABEL_ENV=test jest"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/verdaccio"
|
||||||
|
}
|
||||||
|
}
|
0
docker-examples/v6/apache-verdaccio/README.md → docker-examples/v6/proxy/apache-verdaccio/README.md
0
docker-examples/v6/apache-verdaccio/README.md → docker-examples/v6/proxy/apache-verdaccio/README.md
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: verdaccio-programmatically
|
id: verdaccio-programmatically
|
||||||
title: "Using Verdaccio Programmatically"
|
title: "Node.js API"
|
||||||
---
|
---
|
||||||
|
|
||||||
Verdaccio is a binary command which is available in your enviroment when you install globally the package eg `npm i -g verdaccio`, but also can be dependency in your project and use it programmatically.
|
Verdaccio is a binary command which is available in your enviroment when you install globally the package eg `npm i -g verdaccio`, but also can be dependency in your project and use it programmatically.
|
||||||
|
Loading…
Reference in New Issue
Block a user