Github private packages and docker
November 18, 2020
Photo from https://unsplash.com/@element5digital
Github packages have been around for a while now. As a developer we spend so much time on github either for our office work or for opensource projects.
Couple of months back , our team rolled out a design system, which have a library component also. The library has to be hosted somewhere so that , we can consume it in various projects.
The installation should be very similar to how we do it today mostly with frontend projects using npm install / yarn
We were already having teams licence for organization. we were having all our codebase available on github already. Github packages seemed very legit as an option for private package hosting. We are anyways getting it with the existing licence.
In this article, I am going to explain how we can publish and consume Github packages (private/public) and also what changes needs to be done in Dockerfile to get the installs working for docker builds
Let’s see how we can get it done.
PACKAGE CREATION
Note: If you have js based packages ready , Please dive directly into next section: which is Publish packages
You can create packages in javascript ecosystem using webpack, rollup or grunt/gulp e.t.c .
We used TSDX which is an excellent library creation helper. I also used lerna Lerna for versioining of packages, allthough we will not talk about lerna here.
Let’s create a simple packages which will just give us some random numbers between any two numbers. The example is kept trivial to keep the attention into the most important aspect of this article which are Github Packages
Run
npx tsdx create randomnumberlib
Pick name of your choice for this library, I have chosen randomnumberlib
name. We are going to use https:npm.pkg.github.com
(This is packages namespace for npm with github packages) as the registry for this package. Other languages have their own registeries.
Read more here : Github Packages with npm & Supported github packages client and namespaces
The tsdx command will create a folder , just navigate to the folder in terminal and add your library code. I have added the following code in
src/index.ts
let times = 0
export const random = (min: number, max: number): number => {
if ('development' === process.env.NODE_ENV) {
console.log(`boop ${++times}`);
}
return Math.ceil(Math.random() * (max - min) + min)
};
My function does nothing more than returning a random number between min and max.
PUBLISH PACKAGE
If you have the package already or you have created a package using the steps in above section, let’s dive into how to publish the package.
As it is a github package make sure the package name is in this format
@[username]/[packagename]
. In my case it is@simbathesailor/randomnumberlib
simbathesailor
is mygithub username and randomnumberlib
is the library name
if your package is under any organization, then the above format will become @[organizationnameseenongithub]/[packagename]
. I think most of you reading will have this scenario.
The name attribute in the package.json can be changed to the required package name.
so my package.json will look something like this:
...
"name": "@[organizationnameseenongithub]/[packagename]"
...
For this example , mine package.json looks like this:
"name": "@simbathesailor/randomnumberlib"
First step is to generate a personal access token from https://github.com/settings/tokens.
- Generate the one with read and write packages permission. Copy the token and keep it handy as it is going to be needed soon.
- Run the following command to login to registry.
npm login --registry=https://npm.pkg.github.com
It will prompt for username. Put you github username
Next, it will ask for password: Paste the token generated in step 1.
Next , enter your email attached to your github account against which you want to publish the package.
If every thing works, you should see the message stating that you have successfully logged in.
- Next step : Just run publish command for you library. Run
npm publish
.
This npm publish
will trigger a fresh build(due to prepare npm hook in tsdx, can be different for you) and then will try to publish the package.
By now, you should see the github repository listing package on right handside, somewhat similar to the below snapshot.
Consuming Package [PRIVATE]
- Create a .npmrc file at the level parallel to your package.json file of your project.
- Add following content to the .npmrc file.
@[USERNAME]:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=[YOURTOKEN]
Replace USERNAME
and YOURTOKEN
with the orgname/username and github token(with read packages right) respectively.
If you don’t want to add this file at repository level. You can also keep the same in ~/.npmrc.
- Add .npmrc in
.gitignore
. Because we definitely don’t want to commit token to github.
You can create a .npmrc at ~/.npmrc and put the same content there. That should also work.
- Then just do the normal package install by running below command
There is one more way of doing it.
npm install
If every steps worked fine above, the install would have happened successfully.
And That’s it voila,🎆 you have published and consumed a private package. In my opinion, now with github packages it is very easy to publish and consume private packages as the packages stays near to your code.
To consume a public github package, you can just get rid of follwing line from .npmrc, because now you should bnot be needing any authentication
//npm.pkg.github.com/:_authToken=[YOURTOKEN]
In most of the cases, organizations are using Github plans which automatically allows github packages.
Docker Install
Add the following content to your docker file. Not all the parts are relevant,but the part where I am adding github token can be noticed bit more carefully.
ARG GENERATE_SOURCEMAP
ARG GITHUB_TOKEN
FROM node:12.10 as BUILD
ARG GENERATE_SOURCEMAP
ARG GITHUB_TOKEN
ENV GENERATE_SOURCEMAP $GENERATE_SOURCEMAP
ENV GITHUB_TOKEN $GITHUB_TOKEN
WORKDIR /usr/src/app
COPY package.json .
# Notice part below this line
# This is needed for installing private github packages
RUN echo //npm.pkg.github.com/:_authToken=$GITHUB_TOKEN >> ~/.npmrc
RUN echo @[USERNAME]:registry=https://npm.pkg.github.com/ >> ~/.npmrc
RUN yarn install
# Removing the github token from npmrc file in below line
RUN echo > ~/.npmrc
# Notice part above this line
ADD . /usr/src/app
RUN yarn run build
FROM node:12-alpine3.9
COPY /usr/src/app .
EXPOSE 8001
CMD ["node", "start.js"]
Replace USERNAME
with the your package username/organization.
There are some issue with how the scoped packages are handled via .npmrc. You cannot tell npm to download the packages from different registry at package level. Currently it is at scope level. Below is the ticket that I filed https://github.com/npm/cli/issues/2307
Finally I am going to provide the link where i am consuming the private package. I have added a sample npmrc file also for the reference.
That’s all . Best of luck !!