Send a Slack message when Docker images are updated
I needed a way to send a notification to a Slack channel, whenever I push new versions of Docker images to the registry. This post, I explain how I created a function that uses a container registry webhook to call a serverless function that sends a message to a Slack channel.
curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/[somethingsomething]
{
"id": "673aeeaa-6493-41d3-bcdd-68242942bcb0",
"timestamp": "2020-10-14T00:15:02.82330594Z",
"action": "push",
"target": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1778,
"digest": "sha256:a71f5e4bf56c05a3d6264b8ef4d3bb4c90b4b0af579fedb6ccb68ea59f597435",
"length": 1778,
"repository": "startkubernetes/sk-web",
"tag": "1"
},
"request": {
"id": "adbc2757-8d80-49ac-af5f-ec30e5147bdf",
"host": "myregistry.azurecr.io",
"method": "PUT",
"useragent": "docker/19.03.13+azure go/go1.13.15 git-commit/bd33bbf0497b2327516dc799a5e541b720822a4c kernel/5.4.0-1026-azure os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.13+azure \\(linux\\))"
}
}
{
"text": "This is my message"
}
Note
Slack also has a Block Kit Builder that allows you to build more complex messages.
- Accepts the container registry payload
- Extracts the information (repository, tag, and a timestamp)
- Creates payload that Slack understands
- Sends the payload to the Slack incoming webhook URL.
const axios = require('axios');
const slackUrl = 'https://hooks.slack.com/services/[somethingsomething]';
module.exports = async function (context, req) {
let message = JSON.stringify(req.body);
if (
req.body.hasOwnProperty('target') &&
req.body.hasOwnProperty('timestamp')
) {
const {
target: { repository, tag },
timestamp,
} = req.body;
message = `Pushed image ${repository}:${tag} (${timestamp})`;
} else {
context.res = {
status: 500,
body: req.body,
};
return;
}
axios
.post(
slackUrl,
{ text: message },
{
headers: {
'content-type': 'application/json',
},
}
)
.then((response) => {
context.res = { body: response.body };
})
.catch((err) => {
context.res = {
status: 500,
body: err,
};
context.done();
});
};