---
title: "One-Click Remote Container Deployment with PowerShell — .NET Core to QNAP Docker Container Station"
description: "How to use a PowerShell script to remotely build and deploy a .NET Core application to QNAP NAS Docker Container Station in one click, automating image build, stop, remove, and start steps."
canonical_url: "https://blog.markkulab.net/en/post/qnap-nas-docker-powershell-deployed"
author: "Mark Ku"
author_url: "https://blog.markkulab.net/en/author/mark-ku"
site: "Mark Ku's Tech Notes"
date_published: "2021-12-31 01:01:01 +0800"
category: "PowerShell"
tags: ["qnap", "powershell", "net core", "docker", "deployment", "container"]
language: "en"
license: "CC BY 4.0"
license_url: "https://creativecommons.org/licenses/by/4.0/"
attribution: "when reusing or quoting, credit the author and link back to the original"
---

# One-Click Remote Container Deployment with PowerShell — .NET Core to QNAP Docker Container Station

## One-Click Remote Container Deployment with PowerShell — .NET Core to QNAP Docker Container Station

## Problem Statement

When developing containerized applications on a Windows PC, deploying them to a remote NAS Docker host involved way too many manual steps. I wrote a PowerShell script to automate the entire build and deployment process.

## Development Environment

Windows 10 X64 Home
Visual Studio 2019 Community
Docker for Windows 17.06.2
QNAP NAS TS-253d 5.0.0.1891
Container Station 2.4.3.208
QNAP Docker Version 20.10.8

## Step 1: Download Docker Certificates from the NAS to Your Windows Client

### Go to the NAS admin panel > Open Container Station > Click "Properties" in the left menu > Select "Docker Certificate" > Download

![QNAP Container Station UI: Docker certificate download and environment variable](https://blog.markkulab.net/content/markku/posts/qnap-nas-docker-powershell-deployed/images/2v4Lw0S.png)

Extract the downloaded archive and place the Docker certificates into the `%USERPROFILE%/.docker` directory.

![File Explorer showing highlighted Docker certificate files ca.pem, cert.pem, key](https://blog.markkulab.net/content/markku/posts/qnap-nas-docker-powershell-deployed/images/51PWcNa.png)

Note: `tcp://192.168.50.52:2376` is the Docker host address (this IP and port are no longer active).

## Test the Connection with PowerShell

```
docker --tls -H="tcp://192.168.50.52:2376" --version # 查詢遠端 nas docker 版本號
```

## Writing the PowerShell Remote Deployment Script

### Build the Image

```
# 本地建置映像檔
docker build -t shopcart . -f ./Comma.Web/Dockerfile
# save 要搭配 load 指令; import 搭配 export 指令
docker save -o C:\Project\shopcart.tar shopcart 

$containerUrl = "tcp://192.168.50.52:2376" # 將Nas docker 主機位置宣告成變數

# 遠端建置映像檔 (nas 比本機電腦慢，這個就不建議了)
# docker  --tls -H="$containerUrl" build -t shopcart . -f ./Comma.Web/Dockerfile
```

### Stop the Remote Container

```
$containerName = "shopcart-1" # 容應應用名稱
docker --tls -H="$containerUrl" ps -a -f ancestor=$containerName --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" stop $_ }
docker --tls -H="$containerUrl" ps -a -f name=$containerName --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" stop $_ }
```

### Remove the Remote Container

```
docker --tls -H="$containerUrl" ps -a -f ancestor=$containerName* --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" rm -f $_ }
docker --tls -H="$containerUrl" ps -a -f name=$containerName* --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" rm -f $_ }
```

### Delete the Remote Image

```
$imageName = "shopcart"
$existingImages = docker --tls -H="$containerUrl" images $imageName
If ($existingImages.count -gt 1) {
write-host "[Removing image]Removing the existing image.."
docker --tls -H="$containerUrl" rmi -f $imageName
} else {
write-host "[Removing image]The image does not exist"
}
```

### Load the Local Image onto the Remote Docker Host

```
docker --tls -H="$containerUrl" load --input  "C:\Project\shopcart.tar"
```

### Create and Start the Container

```
docker --tls -H="$containerUrl" run -d --name shopcart-1 -p 888:80 shopcart
```

## Testing It Out

### Double-click the PowerShell script you just wrote

![PowerShell terminal showing Docker container image build and load](https://blog.markkulab.net/content/markku/posts/qnap-nas-docker-powershell-deployed/images/xtHcrwc.png)

### Once the script finishes, check Container Station to confirm the container is running

![Container Station UI showing running Docker containers including shopcart-1](https://blog.markkulab.net/content/markku/posts/qnap-nas-docker-powershell-deployed/images/W9FAEZV.png)

### The web service is displaying correctly

![Web browser displaying a dried fruit store with a coming soon pop-up](https://blog.markkulab.net/content/markku/posts/qnap-nas-docker-powershell-deployed/images/zP3kqp4.jpg)

## Complete Script

```
$hostname = "letgoshop"
$containerName = "shopcart-1"
$containerUrl = "tcp://192.168.50.52:2376"
$imageName = "shopcart"
$containerMacAddress = "00:0C:29:E8:24:F4"
$containerIpAddress = "192.168.0.142"
$logsVolumePath = "/share/Container/Logs"
$dockerfile = "./Comma.Web/Dockerfile"

# 本地建置映像檔
docker build -t shopcart . -f ./Comma.Web/Dockerfile

docker save -o C:\Project\shopcart.tar shopcart # save 指令要搭配 load 指令; import 指令搭配 export 指令

# 遠端建置映像檔 (nas 比本機電腦慢，這個就不建議了)
# docker  --tls -H="$containerUrl" build -t shopcart . -f ./Comma.Web/Dockerfile

# 停用容器
docker --tls -H="$containerUrl" ps -a -f ancestor=$containerName --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" stop $_ }
docker --tls -H="$containerUrl" ps -a -f name=$containerName --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" stop $_ }

# 移除容器
docker --tls -H="$containerUrl" ps -a -f ancestor=$containerName* --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" rm -f $_ }
docker --tls -H="$containerUrl" ps -a -f name=$containerName* --no-trunc -q | foreach-object { docker --tls -H="$containerUrl" rm -f $_ }

# 移除映像檔

$existingImages = docker --tls -H="$containerUrl" images $imageName
If ($existingImages.count -gt 1) {
write-host "[Removing image]Removing the existing image.."
docker --tls -H="$containerUrl" rmi -f $imageName
} else {
write-host "[Removing image]The image does not exist"
}

# 將本地的映像檔匯入 Docker 主機
docker --tls -H="$containerUrl" load --input  "C:\Project\shopcart.tar"
				
# 建立及啟動容器應用
docker --tls -H="$containerUrl" run -d --name shopcart-1 --restart=always -p 8888:80 shopcart			

pause

```

---

## About this article and its author

Originally published on [Mark Ku's Tech Notes](https://blog.markkulab.net/en/post/qnap-nas-docker-powershell-deployed)

License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — when reusing or quoting, credit the author and link back to the original

### About the author

**[Mark Ku](https://blog.markkulab.net/en/author/mark-ku)** — Software Solution Provider

- 10+ years senior software engineer, now an AI Builder
- Focused on large-platform architecture — North-American e-commerce, AI SaaS subscription billing
- Combining AI Agents and automation to build evolvable product foundations

### Free tools built by the author

All of these are free to use:

- [Free PDF Sign Tool](https://blog.markkulab.net/en/tools/pdf-sign): Online PDF sign tool — draw, type, or upload a signature, then drag, resize, and download. Everything runs in your browser; nothing is uploaded.
- [VS Code Refactory](https://blog.markkulab.net/en/tools/refactory): Refactory is a VS Code refactoring extension: 34 actions plus a 37-rule code-smell inspection layer with a Code Health dashboard, across 18 languages, backed by 534 tests. It learns your repo's conventions: where interfaces live, where DI is registered, whether 'use client' belongs. It ranks files by git churn × complexity so you know what to fix first, and hands any smell to the Claude Code already on your machine. Free to use, and your source never leaves your computer.
- [DB-Kit Database Manager](https://blog.markkulab.net/en/tools/db-kit): DB-Kit is a lightweight, cross-platform database manager built with Tauri + Rust + React. Manage MySQL, MariaDB, PostgreSQL, SQL Server, Oracle, SQLite, MongoDB, Redis, Kafka, Elasticsearch and RabbitMQ from one consistent interface: passwords encrypted in the OS keychain, SSH tunnels, full CRUD, a visual query builder, stacked multi-statement result sets, cross-connection data transfer and compare/sync, Excel / CSV import & export, visualized execution plans, ER diagrams, scheduled backups, SQL stress testing with p50–p99 latency percentiles, a 15-rule SQL review engine, Kafka message browsing with monitoring & alerts, a bilingual UI (Traditional Chinese / English), a built-in AI assistant (natural-language SQL, AI review and tuning advice) and the dbk CLI. Free and open source (MIT), with installers for Windows, macOS and Linux.
- [VS Code Super Mermaid](https://blog.markkulab.net/en/tools/super-mermaid): Super Mermaid is a VS Code extension for beautiful Mermaid diagrams out of the box: auto-colored live preview, mouse pan & zoom, high-res PNG / SVG export, 21 templates and multiple themes. Free and open source (MIT).
- [React Super Mermaid](https://blog.markkulab.net/en/tools/react-super-mermaid): react-super-mermaid is an open-source React component library: render beautiful Mermaid diagrams with a single <MermaidViewer>, with built-in colorful / sketch themes, pan & zoom, in-diagram search, and high-res SVG / PNG export. Lightweight, SSR-safe, fully typed. Free and open source (MIT).
- [Jira / Confluence Super Mermaid](https://blog.markkulab.net/en/tools/jira-super-mermaid): An Atlassian Forge app: write Mermaid syntax directly inside a Jira issue or a Confluence page and get flowcharts, sequence diagrams, state machines and Gantt charts. 11 diagram types, SVG / PNG export, light and dark themes, full CJK support. Runs on Atlassian: your diagrams live in your own site and the app calls no third-party service. Free, coming soon to the Atlassian Marketplace.
- [Mermaid Live Preview](https://blog.markkulab.net/en/tools/mermaid-preview): Write Mermaid in your browser, see it render instantly, and share the whole diagram as a single link. No sign-up, nothing uploaded to a server, and mermaid.live share links work as-is.
- [React Intl Phone Number](https://blog.markkulab.net/en/tools/react-intl-phone-number): react-intl-phone-number is an open-source React component: framework-agnostic and antd-free, with E.164 in/out, a searchable flag / country-code dropdown, configurable validation levels (strict / mobile-strict / loose), themeable CSS, and i18n — phone logic powered by google-libphonenumber. Lightweight and fully typed. Free and open source (MIT).
- [Uptime Kuma Cluster](https://blog.markkulab.net/en/tools/uptime-kuma-cluster): Turn single-node Uptime Kuma into a highly available cluster: OpenResty + Lua smart load balancing, shared MariaDB state, health checks and automatic failover, plus cluster-management REST APIs. One Docker Compose command to start. Free and open source (MIT).
- [Special Education](https://blog.markkulab.net/en/education): Learning materials crafted for special education students

### Daily podcasts

- [Mark's Tech Insights — Daily AI News](https://blog.markkulab.net/en/category/tech-news): Daily curated AI and tech trends. Catch the latest developments via audio summaries — covering AI applications, software architecture, DevOps, and engineering practice. — RSS: https://blog.markkulab.net/feed.xml
- [AI股市蝦聊](https://blog.markkulab.net/en/category/ai-stock-chat): Every trading day, an AI-analyzed take on the Taiwan stock market, delivered as a two-host conversation covering the session and the next-day outlook. — RSS: https://blog.markkulab.net/ai-stock-chat/feed.xml
- [開源好物週報](https://blog.markkulab.net/en/category/open-source-weekly): A weekly two-host pick of free open-source tools surfaced from real Hacker News, GitHub, and Reddit buzz — what pain they solve and the fastest way to get started. — RSS: https://blog.markkulab.net/open-source-weekly/feed.xml

### Newsletter

[Subscribe to the newsletter](https://blog.markkulab.net/en/subscribe) — Be the first to know about new posts. No spam, unsubscribe anytime.
