如何在不重启Docker容器的情况下重启服务并拉取Git代码重新运行?
Got it, I totally get that client requirements can push us into less-than-ideal workflows—even though we both know building fresh, immutable images is the right way to go. Let's fix your problem where killing the .NET process took down the entire container, and set up a way to pull code, rebuild, and restart the app without restarting the container.
Why Your Previous Command Broke the Container
The issue is that when you run dotnet filename.dll directly as the container's entrypoint, that process becomes PID 1 inside the container. Docker treats PID 1 as the container's main process—if it exits, Docker stops the whole container. Killing that PID 1 process was the root cause of your container dying.
Fix 1: Use a Wrapper Script as the Container's Main Process
The solution is to run a small bash script as PID 1 instead of the .NET app. This script will handle pulling code, building, starting the app, and restarting it without exiting itself.
Step 1: Create a Startup Script
Make a file named start_app.sh with this content:
#!/bin/bash set -e # Configure these variables to match your repo and project GIT_BRANCH="main" BUILD_COMMAND="dotnet build -c Release" APP_PATH="./bin/Release/net6.0/filename.dll" # Adjust to your output path # Function to restart the app restart_app() { if [ ! -z "$APP_PID" ]; then echo "Stopping running app (PID: $APP_PID)..." kill "$APP_PID" # Wait for the process to exit silently wait "$APP_PID" 2>/dev/null fi } # Listen for SIGUSR1 to trigger a manual restart trap restart_app SIGUSR1 while true; do echo "Pulling latest code from Git..." git pull origin "$GIT_BRANCH" echo "Building the project..." $BUILD_COMMAND echo "Starting the .NET app..." dotnet "$APP_PATH" & APP_PID=$! # Wait for the app to exit (or be killed by the restart trap) wait "$APP_PID" echo "App exited. Restarting in 5 seconds..." sleep 5 done
Step 2: Update Your Dockerfile
Modify your Dockerfile to include the necessary tools (Git, .NET SDK for building) and set the script as the entrypoint:
# Use a base image with .NET SDK (needed for building) FROM mcr.microsoft.com/dotnet/sdk:6.0 AS runtime # Install Git RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* # Set working directory WORKDIR /app # Copy your project files (including .git directory if you're not cloning inside the container) # Alternatively, clone the repo inside the script if you prefer COPY . . # Copy the startup script COPY start_app.sh . RUN chmod +x start_app.sh # Set the script as the entrypoint ENTRYPOINT ["./start_app.sh"]
Step 3: Build and Run the Container
Build the new image and start the container as usual:
docker build -t your-app-image . docker run -d --name your-app-container your-app-image
How to Trigger an Update
Now you have two ways to update the app without restarting the container:
- Automatic Restart: If the .NET app crashes, the script will automatically pull the latest code, rebuild, and restart it after 5 seconds.
- Manual Trigger: Send a
SIGUSR1signal to the script (PID 1 inside the container) to force an immediate update:docker exec your-app-container kill -SIGUSR1 1
Key Notes to Avoid Issues
- Git Credentials: Make sure the container has access to your Git repo. For HTTPS, you can mount a credentials file or use
git configinside the container to set credentials. For SSH, mount your SSH key into the container. - Image Size: Using the .NET SDK image will make your container larger. If this is a problem, you could use a multi-stage build to build first, then copy the output to a runtime image—but you'd still need Git and SDK in the runtime container for on-the-fly builds, which defeats the purpose of a slim runtime.
- Build Cleanup: Add
dotnet cleanbefore the build command if you want to ensure a fresh build every time. - Logging: The script's output will be captured by Docker logs, so you can check progress with
docker logs -f your-app-container.
Fix 2: Modify a Running Container (Not Recommended, But Possible)
If you can't rebuild the image right now, you can manually set up the script inside a running container:
- Enter the container:
docker exec -it your-app-container bash - Install Git (if not already present):
apt-get update && apt-get install -y git - Create the
start_app.shscript as above, make it executable:chmod +x start_app.sh - Stop the current .NET process (but wait—if it's PID 1, killing it will stop the container. So you'll need to first start the script in the background, then kill the .NET process. Alternatively, commit the container to a new image after setting up the script, then restart with the script as entrypoint.)
Again, this is messy—rebuilding the image is the better approach even for this non-ideal workflow.
内容的提问来源于stack exchange,提问作者uopeydel

