Build Node docker image with Azure Devops Npm Registry and Azure Devops Pipelines
Build Node docker image with Azure Devops Npm Registry and Azure Devops Pipelines
This page will explain how to build a docker image of a Node.Js application, that uses a private dependency stored in Azure Devops Artifact Npm Registry.
Note : I will not explain here how to publish a library to an Azure devops Artifact NPM Registry.
Source Code
As explained in the Azure Documentation, in order to use a dependency from Azure Devops Npm Registry, you will need to add an .npmrc
file with the url of the registry.
This Documentation Get started with npm packages in Azure Artifacts will detail how to authenticate and configure Azure Devops NPM Registry.
Build Pipeline
Of course you will have to authenticate from your build execution in order to download the private dependencies.
If you use the Npm@1 task, your task will be automatically authenticated. Azure Pipeline will inject credentials automatically.
- task: Npm@1
displayName: Install NPM Dependencies
inputs:
command: install
workingDir: $(System.DefaultWorkingDirectory)/path/to/node-application
After the execution of this task, you can use npm script and it will be authenticated (as long as you run it in the same job, ie, the same agent).
Pipeline example :
variables:
node_version: 16.19.1
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: $(node_version)
- task: Npm@1
displayName: Install NPM Dependencies
inputs:
command: install
workingDir: $(System.DefaultWorkingDirectory)/path/to/node-application
- script: npm run test
workingDirectory: $(System.DefaultWorkingDirectory)/path/to/node-application
displayName: 'Execute unit tests'
Docker Build
Now imagine you want to build a docker image of your code. As you will have to run an npm install
task during the docker build, you will need to have credentials inside the docker image.
Here is the Dockerfile of my application (this is a typescript application)
FROM node:18.12-alpine As BUILD
WORKDIR /app
COPY tsconfig.json .
# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./
# Copy Authentication
COPY .npmrc .
RUN npm ci
COPY . .
RUN npm run build
FROM node:18.12-alpine
WORKDIR /app
COPY --from=BUILD /app/package*.json ./
COPY --from=BUILD /app/dist dist
# Copy Authentication
COPY --from=BUILD /app/.npmrc .
RUN npm ci --production
# Remove Authentication as it should not be in the final docker image
RUN rm -f .npmrc
EXPOSE 3000
CMD ["npm","start"]
As you can see, we specifically inject the .npmrc
file inside the image (then remove it).
It is important to remove the
.npmrc
file from the image published.
In order to create the .npmrc
file you can inject you will need to inject credentials inside the file.
For that you can use the npmAuthenticate@0 task jsut before the docker build :
- task: npmAuthenticate@0
inputs:
workingFile: $(System.DefaultWorkingDirectory)/path/to/node-application/.npmrc
- task: Docker@1
name: docker_build_image
displayName: 'Docker: Build image'
inputs:
azureSubscriptionEndpoint: 'Your Service Connetion'
azureContainerRegistry: 'my-acr.azurecr.io'
buildContext: path/to/node-application
dockerFile: 'path/to/node-application/Dockerfile'
imageName: my-application:$(Build.BuildNumber)
includeLatestTag: true
I hope this quick article was helpfull, feel free to comment, or react, and if you like … say and share 😃