一次公司内网CICD搭建过程

账号密码


vSphere管理台前端开发账号 xxx.xxx.0.103/ rjkf@VSPHERE.LOCAL xxxxxx9


前端开发centos7 xxx.xxx.0.41 root xxxxxx9


gitlab xxx.xxx.0.41:30300/ root xxxxxx6


jenkins xxx.xxx.0.41:10240/ root xxxxxx6


Harbor xxx.xxx.0.41:30020/ admin xxxxxx5


verdaccio xxx.xxx.0.41:4873/ admin xxxxxx6 admin@xx.com


服务器需求

目前服务器上内存16G,硬盘500G

如果规划k8s最低两台服务器需求


机器A:192.168.1.200 8G内存 20G硬盘 规划安装 Docker、 Kuboard Spray 、Kuboard 、Gitlab 、Harbor 、Jenkins 机器B:192.168.1.201 6G内存 20G硬盘 不要装Docker,规划k8s的master和etcd节点、worker节点


VirtualBox 和 Centos 下载

VirtualBox

ruby 复制代码
https://www.oracle.com/virtualization/technologies/vm/downloads/virtualbox-downloads.html

CentOS 7

centos8 后面gitlab要报权限错误,还是用7就行了

ruby 复制代码
https://mirrors.tuna.tsinghua.edu.cn/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso

手动设置静态ip地址

ifcfg-enp0s3 根据每个机器名字不同,具体要查看 /etc/sysconfig/network-scripts/ 目录下

ini 复制代码
[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-enp0s3
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens160
UUID=0897cf72-aab7-46e4-9c21-76af9adf9ef7
DEVICE=ens160
ONBOOT=yes
IPADDR=xxx.xxx.0.41
GATEWAY=xxx.xxx.0.126
NETMASK=255.255.255.0
DNS1=114.114.114.114
DNS2=8.8.8.8

shell连接服务器

推荐用 MobaXterm_Portable_v23.2.zip,在ftp上已经上传

arduino 复制代码
ftp://xxx.xxx.0.121 
 目录  /工具软件/运维软件   MobaXterm_Portable_v23.2.zip

内网加白地址

公司内网虚拟机需要加白下面这些地址: 国内docker镜像、国内jenkins插件镜像、国内npm仓库、国内yum源

lua 复制代码
mirrors.tuna.tsinghua.edu.cn
mirrors.aliyun.com
mirrors.fedoraproject.org
mirror-icn.yuki.net.uk
mirrors.fedoraproject.org
ung2thfc.mirror.aliyuncs.com
acs-cn-hangzhou-mirror.oss-cn-hangzhou.aliyuncs.com
docker.mirrors.ustc.edu.cn
auth.docker.io
registry-1.docker.io
production.cloudflare.docker.com
hub-mirror.c.163.com
updates.jenkins.io
get.jenkins.io
registry.npm.taobao.org
www.npmjs.com
registry.npmmirror.com
deb.debian.org

设置yum国内源

设置yum源

ini 复制代码
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
         -e 's|^#baseurl=http://mirror.centos.org|baseurl=https://mirrors.tuna.tsinghua.edu.cn|g' \
         -i.bak \
         /etc/yum.repos.d/CentOS-*.repo

更新缓存

yum makecache

Docker 环境安装

bash 复制代码
#关闭防火墙
systemctl stop firewalld && systemctl disable firewalld
​
#安装基础软件包
yum install -y wget lsof net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack yum-utils
​
#配置 docker-ce 国内 yum 源(阿里云),如果失败还是用官网 https://download.docker.com/linux/centos/docker-ce.repo
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
​
#安装 docker 依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
​
#安装 docker-ce
yum install -y docker-ce docker-ce-cli containerd.io
​
#设置开机启动
systemctl enable docker
​
#启动Docker服务
systemctl start docker

Docker 语法

参考 yeasy.gitbook.io/docker_prac...

bash 复制代码
docker pull [image] 拉取镜像
docker images 查看所有镜像
docker ps 查看正在运行的容器
docker ps -a 查看所有容器,包括停止的容器
docker logs [containerID] 查看容器日志 -f 参数就是持续输出日志  
docker containre rm  [containerID] 移除容器
docker container start [containerID] 启动容器
docker container stop [containerID] 停止容器
docker container restart [containerID] 重启容器
docker container update --restart=always [containerID] 更新容器增加restart
docker container exec -it [containerID] /bin/bash  进入容器且启动shell
docker exec -it --user root [containerID] bash  用root进入容器shell
docker container cp [containID]:[/path/to/file]  /path/to/file 从正在运行的 Docker 容器里面,将文件拷贝到本机,两路径可交换
docker run -d --restart always -p 10240:8080 -p 10241:50000 -v /var/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime --name myjenkins jenkins/jenkins 运行jenkins容器,如果没有回下载镜像再安装容器,-d 后台运行  -p 端口映射 -v 目录挂载 --name 设置容器名称
systemctl restart docker 重启docker
docker cp 本地路径 容器id或者容器名字:容器内路径   # 本地到服务器
docker cp 容器id或者容器名字:容器内路径 本地路径   # 服务器到本地
docker run -ti -p 8080:8080 --name node-1 -v $(pwd):/workspace node bash # 可能容器报错就退出了,这样直接进去查看错误
docker logs -fnt mynginx   # 容器启动退出了,可以-fnt查看日志
docker system df   # 查看docker存储情况
docker builder prune --filter  'until=240h' -f  # 保留10天内的docker缓存,清除以前的缓存
docker rmi $(docker images -f "dangling=true" -q) # 清理所有none的镜像
docker rmi -f $(docker images | grep "none" | awk '{print $3}') # 清理所有none的镜像
docker search centos # 查询centos所有版本
docker save -o my_ubuntu_v3.tar runoob/ubuntu:v3 # 保存镜像文件
docker load --input my_ubuntu_v3.tar  # 导入镜像文件

添加国内镜像和内网Harbor的http请求地址

创建或修改/etc/docker/daemon.json文件 默认没有daemon文件,先创建。

rust 复制代码
vi /etc/docker/daemon.json
​
{
  'registry-mirrors': [
    'https://ung2thfc.mirror.aliyuncs.com',
    'https://registry.docker-cn.com',
    'http://hub-mirror.c.163.com',
    'https://docker.mirrors.ustc.edu.cn'
  ],
  'insecure-registries':['xxx.xxx.0.41:30020']
}

加载重启docker,在终端输入以下命令

systemctl daemon-reload
​
systemctl restart docker

测试

arduino 复制代码
docker run hello-world

Gitlab

Gitlab启动很慢,装好后,等待10分钟再看是否启动了,可查看网页是否能访问

bash 复制代码
docker run --detach \
  --publish 30300:80 --publish 30301:443 --publish 30302:22 \
  --name gitlab \
  --restart always \
  --volume $GITLAB_HOME/config:/etc/gitlab \
  --volume $GITLAB_HOME/logs:/var/log/gitlab \
  --volume $GITLAB_HOME/data:/var/opt/gitlab \
  --shm-size 256m \
  gitlab/gitlab-ce:latest

获取root初始密码,这里获取的密码如果不能登录gitlab,直接用第三步重置root密码 注意:The password file will be automatically deleted in the first reconfigure run after 24 hours.

bash 复制代码
docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password

web界面首次修改root密码

右上角 再点击  Edit profile 再点击  password

重置root密码 reset password

bash 复制代码
docker exec -it gitlab bash
gitlab-rake 'gitlab:password:reset[root]'

修改gitllab显示的clone地址,不然是一串数字乱码

bash 复制代码
docker exec -it -u root gitlab bash
vi /opt/gitlab/embedded/service/gitlab-rails/config/gitlab.yml
修改地址 host: xxx.xxx.0.41
        port: 30300
        
   
gitlab-ctl restart

注意:如果gitlab容器重新运行了,那下面host和port需要再次修改

补充 :这里的gitlab.yml并未挂到外部,所以如果docker或服务器重启那这个配置就还原了,需要重写进入来配置和restart,有个办法是运行起来后docker commit gitlab mynewgitlab,把container重新打包镜像,然后增加--volume $GITLAB_HOME/gitlab-rails:/opt/gitlab/embedded/service/gitlab-rails/config 挂载重新运行一个容器,然后把旧容器删掉。

Harbor

Harbor需要docker-compose安装,所以需要下载docker-compose和harbor,docker-compose是批量运行docker容器的工具

docker-compose

docker-compose和harbor安装文件需要从github或者国内镜像kgithub上下载,速度很慢,所以已经放到ftp服务器上

arduino 复制代码
ftp://xxx.xxx.0.121 
 目录  /工具软件/运维软件   docker-compose  harbor-online-installer-v2.8.3.tgz
bash 复制代码
#上传 docker-compose 到 /data/app 目录,这个可以随意
cp /data/app/docker-compose /usr/local/bin/docker-compose
#修改执行权限
chmod +x /usr/local/bin/docker-compose
#软连接映射到/usr/bin/
ln -sf  /usr/local/bin/docker-compose /usr/bin/docker-compose
#验证
which docker-compose
docker-compose version
#解压harbor安装包
tar xf /data/app/harbor-online-installer-v2.8.3.tgz -C /data/app/
#编辑harbor.yml文件
cd /data/app/harbor
cp harbor.yml.tmpl harbor.yml

手动修改harbor配置文件

yaml 复制代码
cd harbor
vi harbor.yml
hostname:   xxx.xxx.0.41   #第5行,主机IP/或者域名
port: 30020    # 第10行,端口可改为 30020
harbor_admin_password: xxxxxx5   #第34行,harbor UI界面admin登陆密码
data_volume: /data/app/harbor-data  #第47行,harbor 持久化数据

#关闭https(把以下的行都注释掉12-18行)
# https related config
#https:
# # https port for harbor, default is 443
# port: 443
# # The path of cert and key files for nginx
# certificate: /your/certificate/path
# private_key: /your/private/key/p

# 安装脚本
运行 ./install.sh

默认账号密码 admin xxxxxx5

设置开机启动

创建文件 /usr/local/bin/harbor/harborstartall.sh,放下面内容

bash 复制代码
#!/bin/bash
cd /usr/local/bin/harbor
docker-compose stop
docker-compose start
chmod 777 /var/run/docker.sock

设置开机启动

bash 复制代码
chmod +x  /usr/local/bin/harbor/harborstartall.sh
#3)把启动脚本加到系统启动之后最后一个执行的文件
echo '/bin/bash /usr/local/bin/harbor/harborstartall.sh'  >>  /etc/rc

jenkins安装

步骤:

  • 1、安装 jenkins docker,要给docker.sock和jennkins_home为777权限
  • 2、默认安装jenkins,默认安装推荐插件
  • 3、配置system三个凭据(gitlab账号密码:gitlabroot,部署服务器ssh密钥:sshserver,推送镜像仓库账号密码:harbor)
  • 4、增加jenkins插件 Git Parameter、SSH Agent
  • 5、web项目根目录建Dockerfile文件,用node镜像打包,用nginx镜像做web服务器
  • 6、jenkins中建项目,建流水线,选SCM并配置信息
  • 7、构建运行两遍

安装

如果docker服务重启后,需要每次执行sudo chmod 777 /var/run/docker.sock,因为jenkins里面不是root会报没权限

bash 复制代码
chmod 777 /var/run/docker.sock
​
mkdir -p /var/jenkins_home
​
chmod 777 /var/jenkins_home
​
docker run -d --restart always -p 10240:8080 -p 10241:50000 -u root -v /var/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker --name jenkins jenkins/jenkins

首次登录密码

bash 复制代码
cat /var/jenkins_home/secrets/initialAdminPassword

安装默认插件

不默认安装插件,因为国内会失败,直接选不安装插件,进入后修改插件地址,再手动安装

参考 zhuanlan.zhihu.com/p/378093468

修改jenkins插件更新地址

在 插件管理中 修改 http://xxx.xxx.0.41:10240/manage/pluginManager/advanced 修改升级站点地址

ruby 复制代码
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

安装额外插件

Git Parameter、SSH Agent 勾选安装后重启 注意:第一次运行会失败,因为是gitParameter依赖与后面checkout的仓库信息

在服务器上生成公私钥

bash 复制代码
ssh-keygen  一直回车就行
​
cd ~/.ssh
​
cat cat id_rsa
​
拷贝打印内容 

添加gitlab、harbor、ssh身份认证

http://xxx.xxx.0.41:10240/manage/credentials/store/system/domain/_/ 地址添加凭证

添加 ssh 凭据

类型选择 SSH Username with private key

id 写 sshserver

username 写 root

Private Key > Enter directly > Add ,将上面rsa私钥全部复制进来

参考:blog.csdn.net/nklinsirui/...

添加 gitlab 凭据

类型选择 Username with password

id 写 gitlabroot

username 和 password 分别写 gitlab创建的账号,我们这里直接用的 root 管理员账号密码

添加 harbor 凭据

类型选择 Username with password

id 写 harbor

username 和 password 分别写 harbor 创建的账号,我们这里直接用的 admin 管理员账号密码

新建流水线项目

选择Pipeline script from SCM或者直接贴下面pipeline内容

dart 复制代码
// 注意先建system凭据

pipeline {
  agent any
	
	environment {
        // 毫秒做镜像标签
        imageTag = sh returnStdout: true, script: "date +%Y%m%d%H%M%S"
        // harbor仓库
		    harborServer = 'xxx.xxx.0.41:30020'
        harborLibrary = 'web'  // 第一次需要在harbor仓库建这个目录
        // git项目
		    gitServer = 'xxx.xxx.0.41:30300'
        gitGroup = 'wms'
        gitProjectName = 'wms-353-web'
        // 后端接口,区分开测试环境和生产环境
        testApiServer = 'http://xxx.xxx.0.41:8088'
        proApiServer = 'https://222.111.113.4:8080'
        // 测试环境前端地址,生产环境只打包镜像不发布
        webHtmlServer = 'xxx.xxx.0.41'
        webHtmlPort = '50090'
    }
    
    parameters {
        gitParameter name:'MR_TO_BRANCH',
                     type:'PT_BRANCH_TAG',
                     branchFilter:'origin/(.*)',
                     defaultValue:'master',
                     selectedValue:'DEFAULT',
                     sortMode:'DESCENDING_SMART',
                     description:'选择分支'
        
        choice(
          choices: "test\npro", name:'buildType', description:'选择发布环境'
        )
    }
	
    stages {
        stage('拉取代码') {
            steps {
                script {
                  if(params.buildType == 'test'){
                    env.testApiServer = env.proApiServer
                  }
                }
                git branch: "${MR_TO_BRANCH}",credentialsId: 'gitlabroot', url: "http://${gitServer}/${gitGroup}/${gitProjectName}.git"
            }
        }
        stage('打包docker') {
            steps {
                script{
                    withCredentials([usernamePassword(credentialsId: 'harbor', passwordVariable: 'harbor_password', usernameVariable: 'harbor_username')]) {
                        sh '''
                            docker login -u ${harbor_username} -p ${harbor_password} ${harborServer}
                            docker build -t ${harborServer}/${harborLibrary}/${gitProjectName}_${buildType}:${imageTag} --build-arg API_SERVER=${testApiServer} .
                            docker push ${harborServer}/${harborLibrary}/${gitProjectName}_${buildType}:${imageTag}
    				            '''
                    }
                }
            }
        }
        stage('清理镜像') {
            steps {
                script{
                  catchError(buildResult:'SUCCESS', stageResult:'SUCCESS'){
                    // 1、清理当前镜像  2、清理10天前历史缓存中间镜像
                    sh '''
                      docker rmi -f ${harborServer}/${harborLibrary}/${gitProjectName}_${buildType}:${imageTag}
                      docker images -f "dangling=true" '--format={{.Tag}} {{.ID}} {{.CreatedAt}}' | awk '{CS=mktime(sprintf("%s %s %s 00 00 00",substr($3,0,4),substr($3,6,2),substr($3,9,2)));ID=$2;NS=systime();DT=NS-10*86400;if(DT > CS){print ID}}' | xargs -r docker rmi -f
                    '''
                    // 不移除空白的镜像,因为那些是docker分层缓存 2023.09.08
                    // docker rmi -f $(docker images | grep "none" | awk '{print $3}')
                    // docker自带清理缓存10天前
                    // docker builder prune --filter  'until=240h' -f
                  }
                }
            }
        }
        stage('部署') {
            steps {
                script{
                  // 测试环境要打包+发布;生成环境只打包
                  if(params.buildType == 'test'){
                      sshagent(credentials: ["sshserver"]) {
                          withCredentials([usernamePassword(credentialsId: 'harbor', passwordVariable: 'harbor_password', usernameVariable: 'harbor_username')]) {
                              // 到远程服务器上建立文件夹 mkdir -p /home/nginx/${gitProjectName}_${buildType}/log 
                              sh '''
                                  ssh -o StrictHostKeyChecking=no -l root ${webHtmlServer} uname -a
                                  docker login -u ${harbor_username} -p ${harbor_password} ${harborServer}
                                  docker ps -a --filter "name=${gitProjectName}_${buildType}" -aq | xargs -r docker rm -f 
                                  docker images | grep "${gitProjectName}_${buildType}" | awk '{print $3}'| xargs -r docker rmi -f
                                  rm -rf /home/nginx/${gitProjectName}_${buildType} && mkdir -p /home/nginx/${gitProjectName}_${buildType}/log
                                  docker run -d --restart always --name ${gitProjectName}_${buildType} -v /home/nginx/${gitProjectName}_${buildType}/log:/var/log/nginx -p ${webHtmlPort}:80 ${harborServer}/${harborLibrary}/${gitProjectName}_${buildType}:${imageTag}
                              '''
                          }
                      }
                  }
                }
            }
        }
        stage('打印结果') {
            steps {
              script {
                echo "本次构建 ${params.buildType} 完成:"
                echo "镜像名:${harborServer}/${harborLibrary}/${gitProjectName}_${params.buildType}:${imageTag}"
                if(params.buildType == 'test'){
                  echo "接口地址: ${testApiServer}"
                  echo "页面地址: http://${webHtmlServer}:${webHtmlPort}"
                }
              }
            }
        }
    }
}

项目根目录建Dockerfile

swift 复制代码
# compile
FROM node:16 as build-stage
WORKDIR /app
COPY package*.json yarn.lock ./
RUN yarn install --registry https://registry.npm.taobao.org
COPY . .
RUN npm run build
​
# production stage
FROM nginx as production-stage
ARG API_SERVER
ENV LANG en_US.UTF-8
ENV API_SERVER=${API_SERVER}
RUN echo "server {  \n\
              listen       80; \n\
              location   /jeecgboot/ { \n\
              proxy_pass              ${API_SERVER}/jeecg-boot/; \n\
              proxy_redirect          off; \n\
              proxy_set_header        Host jeecg-boot-system; \n\
              proxy_set_header        X-Real-IP $remote_addr; \n\
              proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for; \n\
          } \n\
          #解决Router(mode: 'history')模式下,刷新路由地址不能找到页面的问题 \n\
          location / { \n\
              root   /var/www/html/; \n\
              index  index.html index.htm; \n\
              if (!-e $request_filename) { \n\
                  rewrite ^(.*)$ /index.html?s=$1 last; \n\
                  break; \n\
              } \n\
          } \n\
          gzip on; \n\
          gzip_min_length 1k; \n\
          gzip_http_version 1.1; \n\
          gzip_comp_level 6; \n\
          gzip_types text/plain application/x-javascript text/css application/xml application/javascript; \n\
          gzip_vary on; \n\
          access_log  /var/log/nginx/access.log ; \n\
      } " > /etc/nginx/conf.d/default.conf \
    &&  mkdir  -p  /var/www \
    &&  mkdir -p /var/www/html
COPY --from=build-stage /app/dist /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
​

运行一遍后,勾选不允许并发构建,并设置参数化构建过程中高级的列表数量改为10

注意,为了满足多个项目同时打包,最好开起多个执行器

1点击系统管理--》节点配置---》选择master配置从节点,将执行器数量增大即可,比如设置为10

增加 .dockerignore

Dockerfile一般是放到项目根目录,但是在执行docker build时,会讲Dockerfile所在目录所有文件放入daemon上下文中,会导致构建很慢,所以需要.dockerignore把那些不需要的文件夹/文件忽略掉,build和src等要有

csharp 复制代码
.git
node_modules
package-lock.json
pnpm-lock.yaml

运行jenkins

选择分支构建即可 注意运行前面几次可能只有master分支出现,要多等待,可能与 Git Parameter 依赖之前执行的git checkout 信息

Verdaccio搭建

搭建npm私服

新建挂载目录

bash 复制代码
mkdir -p /home/verdaccio/conf
mkdir -p /home/verdaccio/storage
chmod 777 /home/verdaccio

添加配置文件

如果不要权限,设置为$anonymous

yaml 复制代码
vi /home/verdaccio/conf/config.yaml
​
storage: /verdaccio/storage
auth:
  htpasswd:
    file: /verdaccio/conf/htpasswd
uplinks:
  npmjs:
    url: https://registry.npm.taobao.org/
packages:
  '@cy/*':
    access: $all
    publish: $authenticated
    proxy: npmjs
  '@*/*':
    access: $all
    publish: $authenticated
    proxy: npmjs
  '**':
    access: $anonymous
    proxy: npmjs
logs:
  - {type: stdout, format: pretty, level: http}

新建空密码文件,空内容就行

arduino 复制代码
/home/verdaccio/conf/htpasswd

设置权限

bash 复制代码
chown 10001:65533 /home/verdaccio/conf/htpasswd
chown 10001:65533 /home/verdaccio/storage

启动容器

bash 复制代码
docker run -d --restart always --name verdaccio -p 4873:4873 -v /home/verdaccio/storage:/verdaccio/storage -v /home/verdaccio/conf:/verdaccio/conf -v /home/verdaccio/plugins:/verdaccio/plugins verdaccio/verdaccio

即可网页访问 4873端口了

添加用户

arduino 复制代码
npm adduser --registry http://xxx.xxx.0.41:4873/

输入用户名、密码和邮箱。自己设定就行。已经设置了一个账号 admin xxxxxx6 admin@xx.com

登录

arduino 复制代码
npm login --registry http://xxx.xxx.0.41:4873/

publish

当需要把某个项目发布到私有库时,直接 publish。

arduino 复制代码
npm publish --registry http://xxx.xxx.0.41:4873/

发布成功后,刷新页面,就能看到最新发布的包。

主项目使用私服包

1、包项目packages.json中name设置为@cy/xxxx 注意固定前缀为@cy

arduino 复制代码
{
  'name': '@cy/vue2-workflow-designer',
}

2、主项目设置.npmrc

ini 复制代码
registry=https://registry.npmmirror.com
@cy:registry=http://xxx.xxx.0.41:4873/

防火墙端口开起/关闭

css 复制代码
firewall-cmd --zone=public --add-port=5672/tcp --permanent && firewall-cmd --reload  # 开放5672端口
​
firewall-cmd --zone=public --remove-port=5672/tcp --permanent && firewall-cmd --reload #关闭5672端口
​
firewall-cmd --zone=public --list-ports       # 查看防火墙所有开放的端口
​
systemctl start firewalld.service  # 防火墙打开  stop是关闭

nginx

注意需要两次启动nginx,否则报配置文件不存在错误

bash 复制代码
docker run -p 30600:80 --name mynginx -d nginx:latest
​
docker cp mynginx:/etc/nginx /home/nginx
​
docker cp mynginx:/usr/share/nginx/html /home/nginx/html
​
docker rm -f mynginx
​
docker run -p 9001:80 --restart always \
--name mynginx \
-v /home/nginx:/etc/nginx \
-v /home/nginx/log:/var/log/nginx \
-v /home/nginx/html:/usr/share/nginx/html \
-d nginx:latest

前端容器优化策略

Docker 如何缓存前端依赖

参考

juejin.cn/post/715766...

juejin.cn/post/721596...

docker build context 太大问题

css 复制代码
Sending build context to Docker daemon 2G

这个问题需要增加 .gitignore文件,因为 docker build时会根据Dockerfile文件所在位置加载所有同级目录和文件,所以需要排除不拷贝到上下文的文件比如 .git,node_modules

相关推荐
豆豆42 分钟前
为什么用PageAdmin CMS建设网站?
服务器·开发语言·前端·php·软件构建
twins35202 小时前
解决Vue应用中遇到路由刷新后出现 404 错误
前端·javascript·vue.js
qiyi.sky2 小时前
JavaWeb——Vue组件库Element(3/6):常见组件:Dialog对话框、Form表单(介绍、使用、实际效果)
前端·javascript·vue.js
煸橙干儿~~2 小时前
分析JS Crash(进程崩溃)
java·前端·javascript
安冬的码畜日常2 小时前
【D3.js in Action 3 精译_027】3.4 让 D3 数据适应屏幕(下)—— D3 分段比例尺的用法
前端·javascript·信息可视化·数据可视化·d3.js·d3比例尺·分段比例尺
l1x1n03 小时前
No.3 笔记 | Web安全基础:Web1.0 - 3.0 发展史
前端·http·html
昨天;明天。今天。3 小时前
案例-任务清单
前端·javascript·css
zqx_74 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己4 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称5 小时前
Pikachu-csrf-CSRF(get)
前端·csrf