Milind Singh
Software Engineer
12:30 pm - 2:30 pm 21st Sept, 2024
A Linux® container is a set of 1 or more processes that are isolated from the rest of the system.
Linux kernel feature that partition kernel resources such that one set of processes sees one set of resources, while another set of processes sees a different set of resources.
It allows you to allocate resources such as CPU time, system memory, network bandwidth, etc, so that an activity per service instance can be ran and constrained by cgroups on the system.
# CLI to List system namespaces.
lsns --help
# list all ns
lsns
Docker is an open platform for developing, shipping, and running containerized applications.
# 1. Set up Docker's apt repository.
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# 2. Install the Docker packages.
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Docker Service Start
sudo service docker start
# Verify that the Docker Engine installation is successful by running the hello-world image.
sudo docker run hello-world
# download an docker image, eg nginx
docker pull nginx
# run image, use -d to run in background
docker run --name exercise2 -p 8080:80 nginx
# check in browser
http://localhost:8080/
# check docker running process
docker ps
# stop
docker stop exercise2
# restart
docker start exercise2
# check logs
docker logs exercise2
# Get PID for docker container
docker inspect --format '{{.State.Pid}}' exercise2
# List docker container ns
sudo ls -la /proc/7059/ns
A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image.
ADD Add local or remote files and directories.
ARG Use build-time variables.
CMD Specify default commands.
COPY Copy files and directories.
ENTRYPOINT Specify default executable.
ENV Set environment variables.
EXPOSE Describe which ports your application is listening on.
FROM Create a new build stage from a base image.
HEALTHCHECK Check a container's health on startup.
LABEL Add metadata to an image.
MAINTAINER Specify the author of an image.
ONBUILD Specify instructions for when the image is used in a build.
RUN Execute build commands.
SHELL Set the default shell of an image.
STOPSIGNAL Specify the system call signal for exiting a container.
USER Set user and group ID.
VOLUME Create volume mounts.
WORKDIR Change working directory.
# Build a docker container
docker build -t node-api --no-cache .
# Run a docker container
docker run -p 3000:3000 node-api
# Remove image
docker rmi node-api --force
# Clear cache!
docker system prune -a
# Dockerfile
FROM node:22-alpine
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 3000
ENTRYPOINT [ "node", "index.js" ]
gcloud config set project milindsingh
gcloud auth login
gcloud auth configure-docker asia-south2-docker.pkg.dev
docker build -t asia-south2-docker.pkg.dev/milindsingh/docker-meetup/node-api:2024.09.21.1 .
docker push asia-south2-docker.pkg.dev/milindsingh/docker-meetup/node-api:2024.09.21.1
Docker Compose is a tool for defining and running multi-container applications.
# compose.yaml
services:
nginx:
image: "nginx"
ports:
- "80:80"
node:
image: "node"
redis:
image: "redis:alpine"
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
print-message-job:
runs-on: ubuntu-latest
steps:
- name: "printing step"
run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
name: deploy
concurrency: production
on:
push:
branches: [ production ]
workflow_dispatch:
jobs:
release-api:
runs-on: ubuntu-latest
permissions: write-all
name: 'production: release - api'
outputs:
IMAGE_RELEASE_TAG: ${{ steps.create-release.outputs.IMAGE_RELEASE_TAG }}
steps:
- uses: actions/checkout@v4
with:
ref: production
- name: 'create tag and release'
if: success()
uses: actions/github-script@v7
id: create-release
with:
script: |
const { owner, repo } = context.repo
// Generate tag name
let lastestTagName = undefined;
try {
const response = await github.rest.repos.getLatestRelease({
owner,
repo
})
lastestTagName = response?.data?.tag_name
} catch (e) {
}
const date = new Date()
const currentMonth = (date.getMonth() + 1)
let tagName = `${date.getFullYear()}.${currentMonth}.1`
if (lastestTagName != undefined) {
[year, month, increment] = lastestTagName.split(".")
if (date.getFullYear() == year && currentMonth == month) {
increment = (parseInt(increment) + 1)
tagName = `${date.getFullYear()}.${currentMonth}.${increment}`
}
}
// Create a tag
await github.rest.git.createTag({
owner,
repo,
tag: tagName,
message: tagName,
object: context.sha,
type: 'commit',
tagger: {
name: 'Release Pipeline',
email: 'bot@adapttive.com'
}
})
// Create a reference for tag
await github.rest.git.createRef({
owner,
repo,
ref: `refs/tags/${tagName}`,
sha: context.sha
})
console.log(`Release created with tag name: %c${tagName}`, 'color: green');
// Generate Release Notes
const request = {
owner,
repo,
tag_name: tagName,
target_commitish: 'production'
}
if (lastestTagName != undefined) {
request['previous_tag_name'] = lastestTagName
}
const releaseNotes = await github.rest.repos.generateReleaseNotes(request)
let body = releaseNotes?.data?.body != undefined ? releaseNotes.data.body : ""
const addCommits = false;
if (lastestTagName != undefined && addCommits) {
let result = '';
const options = {};
options.listeners = {
stdout: (data) => {
result += data.toString();
}
};
await exec.exec(`git fetch origin`);
await exec.exec(`git fetch --tags`);
await exec.exec(`git log --no-merges --pretty=format:"- %h %s" ${lastestTagName}...${tagName}`, [], options);
body = body + "\n" + result
}
// Get owner and repo from context of payload that triggered the action
const draft = false;
const prerelease = false;
// Create a release
await github.rest.repos.createRelease({
owner,
repo,
tag_name: tagName,
name: tagName,
body,
draft,
prerelease
});
core.exportVariable('IMAGE_RELEASE_TAG', tagName)
core.setOutput('IMAGE_RELEASE_TAG', tagName)
build-api:
runs-on: ubuntu-latest
name: 'production: build - api'
needs: release-api
env:
PROJECT_ID: "milindsingh"
IMAGE_RELEASE_TAG: ${{needs.release-api.outputs.IMAGE_RELEASE_TAG}}
steps:
- uses: actions/checkout@v4
with:
ref: ${{env.IMAGE_RELEASE_TAG}}
- id: 'auth'
uses: 'google-github-actions/auth@v2'
with:
credentials_json: '${{ secrets.PRODUCTION_GCP_CREDENTIALS }}'
- name: 'set up cloud sdk'
uses: 'google-github-actions/setup-gcloud@v2'
with:
version: '>= 462.0.0'
- name: 'use gcloud cli'
run: 'gcloud info'
# format: us-central1-docker.pkg.dev/$PROJECT_ID/$SERVICE_NAME/$IMAGE_NAME:$IMAGE_RELEASE_TAG
- name: 'build docker image'
run: |-
# Build docker image
docker build \
-t asia-south2-docker.pkg.dev/milindsingh/docker-meetup/node-api:$IMAGE_RELEASE_TAG .
- run: |
gcloud auth configure-docker asia-south2-docker.pkg.dev
- name: 'push docker image'
run: |-
docker push asia-south2-docker.pkg.dev/milindsingh/docker-meetup/node-api:$IMAGE_RELEASE_TAG
deploy-api:
runs-on: ubuntu-latest
name: 'production: deploy - api'
needs:
- release-api
- build-api
env:
PROJECT_ID: "milindsingh"
IMAGE_RELEASE_TAG: ${{needs.release-api.outputs.IMAGE_RELEASE_TAG}}
steps:
- id: 'auth'
uses: 'google-github-actions/auth@v2'
with:
credentials_json: '${{ secrets.PRODUCTION_GCP_CREDENTIALS }}'
- name: 'set up cloud sdk'
uses: 'google-github-actions/setup-gcloud@v2'
with:
version: '>= 462.0.0'
- name: 'use gcloud cli'
run: 'gcloud info'
- name: 'deploy image to cloud-run'
run: |-
CLOUDSDK_CORE_DISABLE_PROMPTS=1
gcloud run deploy node-api --image asia-south2-docker.pkg.dev/milindsingh/docker-meetup/node-api:$IMAGE_RELEASE_TAG --region asia-south2
By Milind Singh