MCP-Powered Docker Delivery Agent
Use Copilot, MCP, Docker, CI, and Vercel to ship a protected web dashboard.
Introduction
30 Second Summary
A website change can look finished on your computer while hiding a problem that appears after you share it. Without clear release checks, there is no proof that the same change is safe to publish.
In this project, you will build Deployment Pulse, a dashboard that makes each stage of software delivery visible. You will connect GitHub Copilot Agent mode to the GitHub MCP Server before moving one change through Docker, GitHub Actions, and Vercel.
What You'll Build
You will share a public Deployment Pulse dashboard whose release-ready status proves that the same container passed its required check.
By the end of this project, you'll have:
- A containerized dashboard that opens locally in your browser. Its status reports whether the release gate is ready.
- An AI agent connected to GitHub that can manage repository work from Copilot Chat. It can inspect failed checks using evidence from GitHub Actions.
- A protected release flow where a required check stops failed pull requests before production. Approved changes receive preview deployments before the public dashboard updates.
- Secret Mission: Ship a second dashboard change from a GitHub issue through the protected pipeline. Verify it in a Vercel preview before it reaches production.
Are there any prerequisites?
You need a GitHub account with GitHub Copilot access. Start with Visual Studio Code, Git, and Docker Desktop installed on Windows.
Before We Start
Deployment Pulse is a containerized dashboard that traces AI-assisted delivery across GitHub Copilot Agent mode, the GitHub MCP Server, Docker, GitHub Actions, and Vercel. This opening checkpoint asks you to commit to that goal by explaining why a failed CI check must stop an unreleasable change before production.
Connect Your Delivery Tools
Deployment Pulse needs an agent that can reach GitHub. Without that connection, GitHub Copilot cannot operate repositories or inspect CI evidence.
This step prepares Copilot Agent mode with the GitHub MCP Server. You will also confirm that Docker and Vercel are reachable.
In this step, get ready to:
- Update Visual Studio Code and select Copilot Agent mode.
- Connect Copilot to GitHub repository and GitHub Actions tools through MCP.
- Confirm Docker Desktop and a GitHub-connected Vercel Hobby account are ready.
Update Visual Studio Code and select Agent mode
The remote MCP connection depends on a current version of Visual Studio Code. Copilot Agent mode then becomes the control point for GitHub work later in the project.
- Press the Windows key to open Windows search.
- Type Visual Studio Code into the search field.
- Press Enter to launch Visual Studio Code.
- Select Help from the top menu.
- Select Check for Updates.
- Accept the update prompt if Visual Studio Code finds a newer stable release.
The update may restart Visual Studio Code. This usually takes less than a minute.
- Select the Copilot icon in the Activity Bar to open Copilot Chat.
- Follow the sign-in prompt with the GitHub account that has Copilot access.
- Select Agent in the chat mode selector.
Your editor is now ready to act on reviewed requests. Agent mode can edit files or run commands after you approve its proposed actions.
Copilot Chat missing?
Confirm that the Visual Studio Code update completed. First-time Copilot setup installs the required extensions automatically.
Make sure you used the GitHub account with Copilot access. Help me troubleshoot Copilot Chat or Agent mode in Visual Studio Code.
Connect the GitHub MCP Server
The Model Context Protocol gives Copilot a structured way to call external tools. This connection exposes the GitHub capabilities needed for repositories and CI investigation.
Why use the remote server?
The hosted GitHub MCP Server keeps the server setup outside your computer. Copilot connects to GitHub through one user configuration.
GitHub OAuth handles authorization. You do not need to create or store a personal access token.
- Press Ctrl+Shift+P to open the Command Palette.
- Enter MCP: Open User Configuration into the Command Palette.
- Select MCP: Open User Configuration from the results.
- Paste this configuration into the user configuration editor:
{
"servers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"X-MCP-Toolsets": "default,actions"
}
}
}
}
What does this configuration do?
- The github entry gives the server a recognizable name inside Visual Studio Code.
- The http type connects to GitHub's hosted MCP endpoint.
- The default toolset provides repository and pull request capabilities.
- The actions toolset provides GitHub Actions workflow capabilities.
- Save the user configuration.
- Approve the GitHub OAuth request when it opens.
- Return to Copilot Chat.
- Select Configure tools.
- Confirm that repository tools appear in the available tools list.
- Confirm that issue tools appear in the available tools list.
- Confirm that pull request tools appear in the available tools list.
- Confirm that GitHub Actions tools appear in the available tools list.
GitHub tools missing?
Check that the endpoint and header match the configuration exactly. A missing comma or quote prevents Visual Studio Code from loading the server.
Approve the OAuth request with the same GitHub account used for Copilot. Help me troubleshoot my GitHub MCP Server configuration.
✔️ Awesome, I've got everything!
Great. Double-check that you saved the user configuration before continuing.
ⓧ I'd like to double check the full code
{
"servers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"X-MCP-Toolsets": "default,actions"
}
}
}
}
Start Docker and connect Vercel
Docker Desktop supplies the local container engine used in the next step. Starting it can take about a minute while the engine becomes ready.
- Press the Windows key to open Windows search.
- Type Docker Desktop into the search field.
- Press Enter to launch Docker Desktop.
- Wait for Docker Desktop to report that its engine is running.
Docker Desktop is ready when its engine reports a running state. That local engine can now build the Deployment Pulse image.
The Vercel connection uses your GitHub identity for future deployments. The Hobby plan is free for personal and non-commercial projects.
- Visit the Vercel login page in your browser.
- Select Continue with GitHub.
- Authorize Vercel to access your GitHub account.
- Choose Hobby if Vercel asks you to select a plan.
You now have a GitHub-connected Vercel account. The dashboard confirms that the deployment side of your toolchain is reachable.
Before the final check, do you expect all three connections to report a ready state?
- Switch back to Visual Studio Code.
- Select Terminal from the top menu.
- Select New Terminal.
- Choose PowerShell from the terminal profile selector.
- Check the Docker client and engine by running this command:
docker version
What should I see?
The output contains a Client section and a Server section.
Both sections confirm that the Docker CLI can communicate with the Docker Desktop engine.
- Press Ctrl+Shift+P to open the Command Palette.
- Enter MCP: List Servers into the Command Palette.
- Select MCP: List Servers from the results.
- Confirm that the server list includes github.
- Switch to your browser to confirm that the Vercel dashboard is open under your Hobby account.
The terminal shows both Docker sections. The MCP list shows github. Your browser shows the Vercel dashboard under Hobby.
One connection missing?
- Wait for Docker Desktop to finish starting before checking the Docker output again.
- Reopen the MCP user configuration if the server list does not include github.
- Confirm that Vercel used the same GitHub account you plan to use for this project.
Help me identify which delivery tool is not connected.
Your delivery toolchain is connected. Next, you will use it to create the repository and run Deployment Pulse inside its first local container.
Build the Dashboard Container
Your GitHub Copilot agent can now reach GitHub through the GitHub MCP Server. Your Docker engine is also ready to run the result.
This step gives you a visible local dashboard before the delivery pipeline exists. The missing release file creates a blocked state that your continuous integration check can expose next.
In this step, get ready to:
- Create a public GitHub repository with a matching local workspace.
- Build the Deployment Pulse files into a versioned NGINX container image.
- Run the dashboard locally before committing it to main.
Create the repository and local workspace
The remote repository gives your agent a GitHub destination. A matching local Git repository gives Docker the files it needs to build on your computer.
Keep the repository empty
The local project becomes the first source of files for this repository. Creating a README or another starter file on GitHub would add remote history before your first push.
This repository is public so its standard GitHub-hosted Actions runs stay free. Keep credentials and private information out of every file you add.
- Return to Copilot Chat from earlier.
- Ask Agent to use GitHub MCP to create an empty public repository named mcp-docker-vercel-pipeline.
- Specify that the repository must have no README or other initialization.
- Approve the GitHub tool request if Copilot asks for permission.
- Save the returned HTTPS URL here: repository URL returned by MCP.
Your remote repository now exists without any files. Next, you need a Windows folder with the same name.
- Switch back to the PowerShell terminal from earlier.
- Create the mcp-docker-vercel-pipeline folder on your Desktop by running these commands:
Set-Location ~/Desktop
New-Item -Path "mcp-docker-vercel-pipeline" -ItemType Directory
Set-Location "mcp-docker-vercel-pipeline"
git init -b main
code .
What does this setup do?
- PowerShell moves to your Desktop so the project folder is easy to find.
- The folder name matches the GitHub repository name.
- The git init -b main command creates the local repository with main as its first branch.
- The code . command opens the current folder as your VS Code workspace.
You will see a VS Code window with mcp-docker-vercel-pipeline open. The terminal also confirms that an empty Git repository was initialized.
Folder or VS Code window missing?
Check that PowerShell started from your user account before moving to ~/Desktop. Make sure the folder name is spelled mcp-docker-vercel-pipeline.
If the final command is unavailable, use the VS Code File menu to open the folder from your Desktop.
Help me fix the local workspace setup on Windows.
Create and run the containerized dashboard
The dashboard uses static HTML, CSS, and JavaScript. A versioned NGINX image serves those files through the same container structure on your laptop and later deployment environments.
- Return to Copilot Chat in the mcp-docker-vercel-pipeline workspace.
- Ask Agent to create public/index.html, public/styles.css, public/app.js, Dockerfile, and .dockerignore from the project code.
- Tell Agent to leave public/release.txt absent.
- Tell Agent to leave the workflow absent.
- Review the proposed file changes in Copilot Chat.
- Accept the five files after confirming their paths.
Use the second tab to compare every generated file with the target state. Correct any difference before building the image.
✔️ Awesome, I've got everything!
Your workspace contains the five project files. Confirm that public/release.txt and .github/workflows/container-ci.yml are absent.
ⓧ I'd like to double check the full code
.git
.github
.vscode
README.md
FROM nginx:1.30.6-alpine3.24
COPY public/ /usr/share/nginx/html/
const releaseLabel = document.querySelector("#release-label");
const releaseStatus = document.querySelector("#release-status");
async function checkReleaseGate() {
try {
const response = await fetch("/release.txt", { cache: "no-store" });
if (!response.ok) {
throw new Error(`Release gate returned ${response.status}`);
}
const releaseMessage = (await response.text()).trim();
releaseLabel.textContent = releaseMessage || "Release ready";
releaseStatus.classList.add("ready");
} catch {
releaseLabel.textContent = "Release gate is not ready";
releaseStatus.classList.add("blocked");
}
}
checkReleaseGate();
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Deployment Pulse</title>
<link rel="stylesheet" href="/styles.css">
<script src="/app.js" defer></script>
</head>
<body>
<main class="shell">
<section class="hero">
<p class="eyebrow">MCP-powered delivery</p>
<h1>Deployment Pulse</h1>
<p class="intro">
A containerized dashboard delivered by an AI-assisted GitHub workflow.
</p>
<div class="release-status" id="release-status" aria-live="polite">
<span class="status-dot" aria-hidden="true"></span>
<span id="release-label">Checking release gate...</span>
</div>
</section>
<section class="pipeline" aria-label="Delivery pipeline">
<article class="pipeline-card">
<span class="card-number">01</span>
<h2>Agent</h2>
<p>GitHub Copilot edits the project and responds to CI evidence.</p>
</article>
<article class="pipeline-card">
<span class="card-number">02</span>
<h2>Context</h2>
<p>GitHub MCP connects the agent to repositories, pull requests, and Actions.</p>
</article>
<article class="pipeline-card">
<span class="card-number">03</span>
<h2>Container</h2>
<p>Docker packages the dashboard with a repeatable NGINX runtime.</p>
</article>
<article class="pipeline-card">
<span class="card-number">04</span>
<h2>Delivery</h2>
<p>GitHub Actions validates the image before Vercel serves it.</p>
</article>
</section>
<section class="flow">
<h2>Delivery flow</h2>
<ol>
<li>Copilot prepares a reviewed change.</li>
<li>GitHub Actions builds and checks the container.</li>
<li>A required check protects the production branch.</li>
<li>Vercel publishes the approved Docker image.</li>
</ol>
</section>
</main>
</body>
</html>
:root {
color-scheme: dark;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: #07111f;
color: #e8f0ff;
}
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
background:
radial-gradient(circle at top left, rgba(66, 211, 146, 0.18), transparent 34rem),
linear-gradient(145deg, #07111f 0%, #0d1a2b 55%, #10253a 100%);
}
.shell {
width: min(1080px, calc(100% - 2rem));
margin: 0 auto;
padding: 4rem 0;
}
.hero,
.flow {
border: 1px solid rgba(173, 206, 255, 0.18);
border-radius: 1.5rem;
background: rgba(8, 20, 35, 0.78);
box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.28);
}
.hero {
padding: clamp(2rem, 7vw, 5rem);
}
.eyebrow,
.card-number {
color: #6ee7b7;
font-size: 0.78rem;
font-weight: 800;
letter-spacing: 0.14em;
text-transform: uppercase;
}
h1 {
max-width: 12ch;
margin: 0.5rem 0 1rem;
font-size: clamp(3rem, 9vw, 6.5rem);
line-height: 0.94;
}
.intro {
max-width: 42rem;
color: #b8c7dc;
font-size: 1.1rem;
line-height: 1.7;
}
.release-status {
display: inline-flex;
align-items: center;
gap: 0.7rem;
margin-top: 1rem;
padding: 0.75rem 1rem;
border: 1px solid #f59e0b;
border-radius: 999px;
color: #fcd34d;
background: rgba(245, 158, 11, 0.1);
}
.status-dot {
width: 0.65rem;
height: 0.65rem;
border-radius: 50%;
background: currentColor;
box-shadow: 0 0 1rem currentColor;
}
.release-status.ready {
border-color: #34d399;
color: #6ee7b7;
background: rgba(52, 211, 153, 0.1);
}
.release-status.blocked {
border-color: #f87171;
color: #fca5a5;
background: rgba(248, 113, 113, 0.1);
}
.pipeline {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
margin: 1rem 0;
}
.pipeline-card {
min-height: 15rem;
padding: 1.4rem;
border: 1px solid rgba(173, 206, 255, 0.16);
border-radius: 1.2rem;
background: rgba(12, 29, 48, 0.82);
}
.pipeline-card h2,
.flow h2 {
margin: 1rem 0 0.7rem;
}
.pipeline-card p,
.flow li {
color: #aebed3;
line-height: 1.65;
}
.flow {
padding: 2rem;
}
.flow ol {
margin-bottom: 0;
padding-left: 1.4rem;
}
@media (max-width: 800px) {
.pipeline {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 520px) {
.shell {
padding: 1rem 0;
}
.pipeline {
grid-template-columns: 1fr;
}
}
- Correct any differences you found in the generated files.
- Save all five files.
Expect the first build to take a few minutes while Docker downloads the versioned NGINX image. A quiet pause during that download is normal.
- Build the local image by running this command in the VS Code PowerShell terminal:
docker build --tag deployment-pulse:local .
What does this build do?
- Docker reads the Dockerfile from the current folder.
- The build starts from nginx:1.30.6-alpine3.24 so the runtime version stays consistent.
- The COPY instruction places the dashboard inside NGINX's static content directory.
- The tag deployment-pulse:local gives the finished image a reusable local name.
The build completes successfully with an image tagged deployment-pulse:local. Your dashboard is now packaged with its web server.
Docker build failing?
Confirm that Dockerfile is inside the open mcp-docker-vercel-pipeline folder. Check that its first line matches the full-code reference.
Confirm that Docker Desktop is still running if the terminal cannot reach the Docker engine.
Help me diagnose my Deployment Pulse Docker build.
- Start the dashboard container by running this command:
docker run --detach --name deployment-pulse --publish 127.0.0.1:8080:80 deployment-pulse:local
What does this command do?
- The --detach option leaves the container running in the background.
- The --name deployment-pulse option assigns a stable container name.
- The --publish 127.0.0.1:8080:80 option sends local port 8080 traffic to NGINX on port 80.
- Binding to 127.0.0.1 keeps this development server available only from your computer.
The terminal prints a container identifier. That output confirms the deployment-pulse container started in the background.
Container not starting?
A name conflict means another container already uses deployment-pulse. A port conflict means another process already owns local port 8080.
Help me diagnose why the Deployment Pulse container will not start.
Publish and verify the blocked release
Your running container proves that the static application works locally. Publishing this baby version gives the next CI change a stable baseline on main.
- Return to the VS Code PowerShell terminal in mcp-docker-vercel-pipeline.
- Stage the project and push the initial commit by running these commands:
git add .
git commit -m "Build containerized deployment dashboard"
git remote add origin [[REPOSITORY_URL="repository URL returned by MCP"]]
git push -u origin main
What does this publish?
- The first command stages the five project files.
- The commit records the working dashboard as one project milestone.
- The remote command connects this local repository to the HTTPS URL returned by GitHub MCP.
- The push uploads main and establishes it as the tracked upstream branch.
The push completes with main tracking the remote branch. Your public GitHub repository now contains the same five files as your local workspace.
Push rejected or authentication requested?
Confirm that the saved repository URL belongs to mcp-docker-vercel-pipeline. Complete the GitHub authentication flow if Git Credential Manager opens it.
A remote history conflict usually means the GitHub repository was initialized with a starter file. Use the empty repository created through MCP for this project.
Help me troubleshoot the first push to my GitHub repository.
Before you load the page, picture the release state you expect from a dashboard with no public/release.txt file.
- Switch back to the browser from earlier.
- Enter http://127.0.0.1:8080 in the address bar.
- Load the local dashboard.
You will see the Deployment Pulse heading with four pipeline cards. The status reads Release gate is not ready because the request for /release.txt cannot find that file.
Why is the blocked status useful?
The container can serve the dashboard while still failing its release contract. This separates local availability from release readiness.
That gap gives your future CI check something concrete to detect. A working page alone does not prove that an image is ready for production.
Dashboard not loading?
Confirm that the URL uses local port 8080. Keep Docker Desktop running while the browser connects to the container.
If the page loads without its styling, compare the paths in public/index.html with public/styles.css and public/app.js.
Help me troubleshoot the local Deployment Pulse page.
That is your first delivery milestone complete. The app is packaged, running locally, and reporting the missing release contract exactly as designed.
Your working container is now the baseline on main. Next, you will make CI test the missing release contract and stop the incomplete image from moving forward.
Protect, Repair, and Deploy
Your local Docker container already serves Deployment Pulse. The blocked release message proves the dashboard can detect an incomplete delivery state.
A working local page still needs independent release evidence. GitHub Actions will test the image through CI before branch protection allows a merge.
The GitHub MCP Server gives GitHub Copilot access to the failure evidence. Vercel will publish the merged image as your production service.
In this step, get ready to:
- Create a protected pull request that exposes the missing release contract.
- Use CI evidence to repair the release gate before merging.
- Deploy the approved Docker image to a public Vercel production URL.
Make CI expose the release gap
A feature branch gives the workflow a safe place to prove whether the image satisfies its release contract. The pull request keeps that evidence separate from main.
- Create the release-gate branch in the VS Code PowerShell terminal by running this command:
git switch -c ci/release-gate
What does this command do?
The command creates ci/release-gate from your current commit. It also switches your local repository to that branch.
- Confirm the VS Code status bar now shows ci/release-gate.
Branch not created?
Check that the PowerShell terminal is still inside the local mcp-docker-vercel-pipeline folder. A message mentioning an existing branch means you can switch to that branch instead.
Help me fix the feature branch in my local repository.
The workflow builds the same Dockerfile on a clean runner. Its final HTTP check defines the release contract that every pull request must satisfy.
- In Copilot Chat, ask Agent mode to create .github/workflows/container-ci.yml using the workflow in the comparison tab below.
- Review the generated diff for changes outside .github/workflows/container-ci.yml.
✔️ Awesome, I've got everything!
- Save .github/workflows/container-ci.yml after confirming that the generated workflow matches the requested file.
ⓧ I'd like to double check the full code
name: Container CI
on:
pull_request:
branches:
- main
push:
branches:
- main
permissions:
contents: read
jobs:
verify-container:
name: Verify Docker release
runs-on: ubuntu-24.04
steps:
- name: Check out repository
uses: actions/checkout@v6.2.0
- name: Build container
run: docker build --tag deployment-pulse:ci .
- name: Start container
run: docker run --detach --name deployment-pulse --publish 127.0.0.1:8080:80 deployment-pulse:ci
- name: Wait for HTTP server
run: curl --fail --silent --retry 5 --retry-connrefused --retry-delay 1 --output /dev/null http://127.0.0.1:8080/
- name: Verify release gate
run: curl --fail --silent --output /dev/null http://127.0.0.1:8080/release.txt
- name: Clean up container
if: ${{ always() }}
run: docker rm --force deployment-pulse
What does this workflow do?
- The workflow runs for pull requests into main.
- The workflow also runs for pushes to main.
- The Verify Docker release job builds the project image on ubuntu-24.04.
- The HTTP checks verify the dashboard route plus the release contract.
- The final cleanup step removes the test container after every outcome.
Before you push the workflow, make a prediction about whether its release check will pass or fail:
- Commit the workflow to the feature branch by running these commands:
git add .github/workflows/container-ci.yml
git commit -m "Add container release gate"
git push -u origin ci/release-gate
What do these commands do?
The first command stages the workflow file. The second command records it in the branch history.
The final command publishes ci/release-gate to origin.
Push rejected?
Check that origin still points to the public mcp-docker-vercel-pipeline repository. Complete any GitHub authentication prompt that appears.
Help me diagnose why my feature branch will not push to GitHub.
- In Copilot Chat, ask Agent mode to use GitHub MCP to open a pull request from ci/release-gate into main.
The first workflow run can take longer while the runner pulls the NGINX image. A waiting check during that pull is expected.
Before you inspect the run, make a prediction about the result of the release contract:
- Open the pull request's Verify Docker release check after the run finishes.
You will see a red check. Its log reports an HTTP 404 for /release.txt.
This failure is intentional
The image itself built successfully. The HTTP check found that the release contract is missing.
This is the evidence branch protection needs. A locally working container cannot reach production while its required release endpoint returns a failure.
The failed check now exists in the repository history. GitHub can use that named result as a required gate for main.
- Select Settings in the repository header.
- Select Branches in the repository settings.
- Choose Add classic branch protection rule.
- Enter main in Branch name pattern.
- Enable Require a pull request before merging.
- Enable Require status checks to pass before merging.
- Select Verify Docker release as the required status check.
- Enable Do not allow bypassing the above settings.
What does this protection enforce?
Every change to main must arrive through a pull request. The selected release check must pass before GitHub permits the merge.
The bypass setting applies the same gate even when someone has elevated repository access.
- Select Create to save the branch protection rule.
- In Copilot Chat, ask Agent mode to use GitHub MCP to inspect the failed Actions logs without changing any files.
Copilot should identify the failed HTTP request to /release.txt from the MCP-retrieved evidence. Your source files remain unchanged at this point.
Repair the contract and merge
The failed request identifies a precise contract gap. The smallest repair is a release artifact that the existing application already knows how to read.
- In Copilot Chat, ask Agent mode to explain the MCP-retrieved failure.
- Ask Agent mode to propose public/release.txt as the smallest valid repair.
- Review the proposed diff before accepting it.
- Confirm that public/release.txt contains exactly this line:
Release ready: CI-approved container
Why does this repair work?
The workflow requests /release.txt from the running image. NGINX serves this new file from the copied public content.
The browser code reads the same response into releaseMessage. It also adds the ready class through releaseStatus.
✔️ Awesome, I've got everything!
- Save public/release.txt with the accepted repair.
ⓧ I'd like to double check the full code
Release ready: CI-approved container
What should the file contain?
The file contains one release message followed by a newline. Extra labels would change the status displayed by the dashboard.
Before you push the repair, make a prediction about whether the same pull request check will pass:
- Commit the release artifact to the current branch by running these commands:
git add public/release.txt
git commit -m "Satisfy release gate"
git push
What happens after the push?
The new commit updates the existing pull request. GitHub Actions starts the same Container CI workflow against the repaired image.
The comparison is controlled because the workflow stays unchanged. Only the missing release artifact has been added.
Check still failing?
Confirm that the file path is exactly public/release.txt. Confirm that the committed content matches the release message exactly.
Help me diagnose why Verify Docker release still fails after adding public/release.txt.
- Return to the existing pull request.
- Wait for Verify Docker release to turn green.
- In Copilot Chat, ask GitHub MCP to inspect the latest workflow run until it reports success.
- Complete the pull request merge after the required check is green.
- Ask GitHub MCP to confirm that the pull request is merged.
- Ask GitHub MCP to confirm that the workflow run on main completed successfully.
That is the release gate working end to end. The protected branch rejected incomplete delivery evidence before accepting the repaired image.
Deploy the approved image to Vercel
The merged Dockerfile now represents an image that passed the same contract on main. Vercel can build that root Dockerfile into a public Container Function.
- Return to the Vercel dashboard from earlier.
- Select New Project.
- Select the mcp-docker-vercel-pipeline repository from GitHub.
Repository missing?
Select Adjust GitHub App Permissions or Configure GitHub App. Grant Repository access to mcp-docker-vercel-pipeline.
Select Save before returning to the import screen. Help me restore Vercel access to my GitHub repository.
- Keep the project root set to the repository root.
- Confirm that Vercel selects the Container preset from the root Dockerfile.
- Keep the project on Hobby.
The first cloud build may take longer while Vercel pulls the NGINX base image. The deployment activity shows that the build is still progressing.
- Select Deploy to build the production Container Function.
Vercel completes the deployment with a generated production URL. The project now serves the image merged from main.
- Record the generated production URL here: your Vercel production URL.
Before you load the production URL, make a prediction about the release state the browser will show:
- Open your Vercel production URL in your browser.
You will see Deployment Pulse with Release ready: CI-approved container. The status uses the green styling from the ready class.
- Select Deployments in the Vercel project.
- Open the production deployment.
You should see that the production deployment came from main. You should also see that Vercel used the Docker image through the Container preset.
You have taken one image from a local warning to a protected public release. The same release contract now governs development evidence plus production behavior.
Secret mission
Ship an Issue-Driven Preview
Your first release proved the delivery pipeline once. This mission sends an issue-driven dashboard change through required CI, a Vercel preview, and production.
Clean Up Your Resources
Clean Up Your Resources
Your delivery pipeline remains online after the project. The planned path costs $0 within Vercel Hobby's included usage.
Resources you used:
- The complete public mcp-docker-vercel-pipeline repository on GitHub.
- The deployment-pulse container in Docker.
- The local Docker image tagged deployment-pulse:local.
- The Vercel Hobby project with all associated deployment resources.
Keep everything running
No action needed. Choose this option if you want the public dashboard to stay available.
- Keep the public mcp-docker-vercel-pipeline repository available for future changes.
- Leave the Vercel project active to preserve the production URL.
- Keep the deployment-pulse container available for local runs.
- Keep the deployment-pulse:local image available for new containers.
- Monitor the Usage page if you expand the project beyond its current traffic.
Pause - I'll come back to this later
Pausing stops public traffic while preserving your Vercel project. Your GitHub repository stays unchanged.
- Return to your Vercel project.
- Select Settings.
- Select General.
- Select Pause Project.
Visitors now receive 503 DEPLOYMENT_PAUSED. You can restore production traffic with Resume Project.
- Free local memory by removing the running container with this command:
docker rm --force deployment-pulse
What does this command do?
The docker rm command removes the named container. The --force option stops it first when it is running.
The local deployment-pulse:local image stays available for your next local run.
Container already removed?
If Docker reports that the container is missing, there is nothing left to pause locally.
Help me check whether the deployment-pulse Docker container still exists on Windows.
Delete - I don't want to use this again
Deleting the hosted resources is permanent. Your local source files remain on your computer as a backup.
Delete the Vercel project:
- Return to your Vercel project.
- Select Settings.
- Select General.
- Find Delete Project.
- Select Delete.
- Select Continue.
The Vercel project disappears with its production deployment. Its preview deployments are also removed.
Delete the GitHub repository:
- Return to the public mcp-docker-vercel-pipeline repository.
- Select Settings.
- Select General.
- Scroll to Danger Zone to find the repository deletion control.
- Use the repository deletion control to delete mcp-docker-vercel-pipeline.
- Complete GitHub's confirmation prompts.
The repository disappears with its complete project history.
Remove the local Docker resources:
- Remove the deployment-pulse container plus the deployment-pulse:local image by running these commands:
docker rm --force deployment-pulse
docker image rm deployment-pulse:local
What do these commands remove?
- The docker rm --force deployment-pulse command stops the local container before removing it.
- The docker image rm deployment-pulse:local command removes the tagged image after the container is gone.
Resource already missing?
A missing container or image means that resource has already been removed. Continue with any cleanup actions that remain.
Help me verify that the Deployment Pulse Docker resources are removed.
The teardown is complete. Every resource listed above is now removed.
Nice Work!
Nice Work!
You did it! Deployment Pulse now has a protected delivery path from an AI-assisted change to a public production dashboard.
You've learned how to:
- Connected GitHub Copilot Agent mode to repository tools through the GitHub MCP Server. You used that connection to create pull requests. You also inspected workflow evidence without leaving your coding environment.
- Built Deployment Pulse as an NGINX-based Docker image. GitHub Actions exposed the missing public/release.txt contract through a designed CI failure. You used the failed run as evidence for the repair.
- Protected main with the required Verify Docker release check. Vercel published the approved image as a public Container Function with the release-ready status.
- Secret Mission: Shipped an issue-driven Environment card through the required check. You tested it in a Vercel preview before merging it into production.
Ready to quiz yourself?