借助GitLab CI/CD将Angular 5应用部署到自有基础设施
Hey there! I’ve set up this exact workflow before for Angular 5 apps deployed to a self-hosted Ubuntu server via GitLab CI/CD, so let’s break this down step by step. First, we’ll get your server ready, then dive into the .gitlab-ci.yml example, and wrap up with best practices to keep things smooth.
Before configuring CI/CD, your server needs a few things to host the Angular app and accept deployments:
a. Set Up a Web Server (Nginx Example)
Angular builds to static files, so we’ll use Nginx to serve them:
# Install Nginx sudo apt update && sudo apt install nginx -y # Create a site config for your app sudo nano /etc/nginx/sites-available/angular-app
Paste this config (replace your-server-ip-or-domain with your server’s actual IP or domain):
server { listen 80; server_name your-server-ip-or-domain; root /var/www/angular-app/dist; index index.html; # Handle Angular's client-side routing location / { try_files $uri $uri/ /index.html; } }
Enable the site and restart Nginx:
sudo ln -s /etc/nginx/sites-available/angular-app /etc/nginx/sites-enabled/ sudo systemctl restart nginx
b. Configure SSH Access for the Runner
The GitLab Runner needs passwordless SSH access to your server to transfer files. Here’s how:
- On the Runner’s Ubuntu machine, generate an SSH key pair (if you don’t already have one):
ssh-keygen -t ed25519 -C "gitlab-runner@your-runner-machine" - Copy the public key to your deployment server:
ssh-copy-id your-server-username@your-server-ip-or-domain - Verify the Runner can connect without a password:
ssh your-server-username@your-server-ip-or-domain
c. Fix Directory Permissions
Make sure the Runner user has write access to the app directory on the server:
sudo mkdir -p /var/www/angular-app sudo chown -R your-server-username:your-server-username /var/www/angular-app
.gitlab-ci.yml Example for Angular 5 This config splits the workflow into three stages: install dependencies, build the app, and deploy to your server.
stages: - install_deps - build - deploy # Global variables - adjust these to match your setup variables: NODE_VERSION: 12 # Angular 5 requires Node >=8.9, 12 is a stable choice APP_NAME: angular-app DEPLOY_SERVER: your-server-ip-or-domain DEPLOY_USER: your-server-username DEPLOY_PATH: /var/www/$APP_NAME # Stage 1: Install dependencies and cache them install_deps: stage: install_deps image: node:$NODE_VERSION script: # Install the exact Angular CLI version compatible with Angular 5 - npm install -g @angular/cli@1.7.4 - npm install cache: paths: - node_modules/ only: - main # Trigger only on main branch (adjust to your primary branch) # Stage 2: Build the app for production build: stage: build image: node:$NODE_VERSION script: # Production build with optimizations for Angular 5 - ng build --prod --build-optimizer artifacts: paths: - dist/ expire_in: 1 week # Clean up old build artifacts after 1 week dependencies: - install_deps only: - main # Stage 3: Deploy to your server deploy: stage: deploy image: alpine:latest # Lightweight image for SSH/rsync before_script: - apk add --no-cache openssh-client rsync - mkdir -p ~/.ssh # Load the private key from GitLab CI variables (see note below) - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan $DEPLOY_SERVER >> ~/.ssh/known_hosts script: # Sync the built files to the server - rsync -avz --delete dist/ $DEPLOY_USER@$DEPLOY_SERVER:$DEPLOY_PATH/dist/ # Reload Nginx to serve the new content - ssh $DEPLOY_USER@$DEPLOY_SERVER "sudo systemctl reload nginx" dependencies: - build only: - main when: manual # Optional: Require manual approval for deployments (great for production)
Important Note About SSH_PRIVATE_KEY
Don’t hardcode your SSH private key! Instead:
- Go to your GitLab project → Settings → CI/CD → Variables
- Add a new variable named
SSH_PRIVATE_KEY - Paste the content of your Runner’s private key (from
~/.ssh/id_rsa) - Check Protected and Masked to keep the key secure
Here are the rules I follow to keep CI/CD reliable and efficient:
- Cache Aggressively: The
install_depsstage cachesnode_modulesso you don’t re-download dependencies every time. This cuts down CI run time drastically. - Use Exact Versions: Pin Angular CLI and Node versions (like
@angular/cli@1.7.4andnode:12) to avoid unexpected breaks from version updates. - Isolate Stages: Splitting into install/build/deploy makes it easy to debug failures (e.g., if deployment fails, you know the build worked).
- Manual Deployment for Production: Use
when: manualfor production deployments to prevent accidental pushes to live servers. - Clean Up Artifacts: The
expire_insetting ensures old build files don’t clog up GitLab’s storage. - Secure Variables: Always store sensitive data (like SSH keys, API tokens) in GitLab’s CI variables, never in your repo.
- Monitor Logs: Check GitLab’s CI job logs regularly—they’ll tell you exactly where a deployment went wrong (e.g., SSH connection issues, build errors).
- Environment Isolation: If you have test/staging/production environments, use GitLab’s Environments feature to manage separate deployment targets for each.
内容的提问来源于stack exchange,提问作者Michael Adlhoch

