Frp内网穿透（使用自己的服务器将 本地服务 映射到外网）
Frp内网穿透frp 是什么？frp 是一个专注于内网穿透的高性能的反向代理应用，支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。前提: 具有一台公网Ip的服务器下载frp解压缩下载的压缩包，将其中的 frpc 拷贝到内网服务所在的机器上，将 frps 拷贝到具有公网 IP 的机器上，放置在任意目录。配置fprs.ini[common] # frp的连接端口 bind_port = 7000 # 开放web 8080 端口 vhost_http_port = 8080 # 服务端密钥 token = tanghaofu # frp管理后台端口，请按自己需求更改 dashboard_port = 7500 # frp管理后台用户名和密码，请改成自己的 dashboard_user = yiyu dashboard_pwd = yiyu enable_prometheus = truefrpc.ini[common] # 需要连接的公网Ip地址 server_addr = 111.230.199.117 # 公网ip的frp端口 server_port = 7000 # 客户端密钥 token = tanghaofu # 创建一个基于tcp类型的连接 [我的世界内网穿透] type = tcp # 本地需要暴露到公网的服务地址 local_ip = 127.0.0.1 # 本地需要暴露到公网的服务端口 local_port = 25565 # remote_port 表示在 frp 服务端监听的端口，访问此端口的流量将会被转发到本地服务对应的端口 remote_port = 25565 # 开放一个http类型的连接 [测试本地web应用] type = http # 映射到本地的8080端口 local_port = 8080 custom_domains = 111.230.199.117启动命令服务端: ./frps -c ./frps.ini客户端: ./frpc -c ./frpc.ini
Docker-Compose总集MYSQLdocker-compose.ymlversion: "3.8" services: mysql: image: mysql:8.1 #镜像名称以及版本 #限制docker容器的内存 deploy: resources: limits: memory: 1G restart: always #重启docker后该容器也重启 container_name: mysql8 #容器名称 environment: MYSQL_ROOT_PASSWORD: root #指定用户密码 TZ: Asia/Shanghai ports: - 3306:3306 #本地端口号与容器内部端口号 volumes: #指定挂载目录 - ./data:/var/lib/mysql - ./conf/my.cnf:/etc/mysql/my.cnfmy.cnf[mysqld] user=mysql default-storage-engine=INNODB character-set-server=utf8 max_connections=1000 bind-address = 0.0.0.0 [client] default-character-set=utf8mb4 [mysql] default-character-set=utf8mb4 Redisdocker-compose.ymlversion: "3.8" services: redis: restart: always image: redis ports: - 6379:6379 volumes: - ./config:/opt/config - ./data:/data command: redis-server /opt/config/redis.conf container_name: redisredis.conf# 开启 AOF 持久化 appendonly yes # 指定 AOF 文件名 appendfilename "appendonly.aof" # 指定 AOF 文件保存目录 dir /data # 关闭 RDB 持久化 save "" # 开启 RDB 持久化 #save 900 1 #save 300 10 #save 60 10000 # 禁用 Redis 的保护模式，允许外部连接 protected-mode no # 允许其他服务访问 bind 0.0.0.0 # 指定 Redis 监听的端口 port 6379 # 指定日志生成的文件 #logfile /var/log/redis/redis.log Elasticsearchdocker-compose.ymlversion: "3.8" services: elasticsearch: image: elasticsearch:8.1.0 container_name: elasticsearch # restart: always ports: - 9200:9200 - 9300:9300 environment: - TZ=Asia/Shanghai - discovery.type=single-node - ES_JAVA_OPTS=-Xms1024m -Xmx1024m volumes: # - ./config:/usr/share/elasticsearch/config - ./plugins:/usr/share/elasticsearch/plugins networks: - elastic kibana: container_name: kibana image: kibana:8.1.0 ports: - 5601:5601 networks: - elastic networks: elastic: driver: bridge Jenkinsdocker-compose.ymlversion: "3.8" services: jenkins: image: jenkins/jenkins:2.401.3-lts-jdk17 container_name: jenkins restart: always ports: - 8081:8080 - 50000:50000 volumes: - ./data/:/var/jenkins_home/ - /var/run/docker.sock:/var/run/docker.sock - /usr/bin/docker:/usr/bin/docker - /etc/docker/daemon.json:/etc/docker/daemon.json - ./java.security:/opt/java/openjdk/conf/security/java.security environment: - TZ=Asia/Shanghai 若要拉取SVN代码需要将java.security文件中的该Key改为下方对应的值jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL在Jenkins中使用外部Docker命令将外部的docker.sock文件改成root用户并且授权cd /var/run chown root:root docker.sock chmod o+rw docker.sockMiniodocker-compose.ymlversion: "3.8" services: minio: # minio/minio:RELEASE.2025-04-22T22-12-26Z 带管理菜单 # 无管理菜单解决方案：https://blog.csdn.net/hyh17808770899/article/details/148958873?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-148958873-blog-148287799.235^v43^pc_blog_bottom_relevance_base6&spm=1001.2101.3001.4242.1&utm_relevant_index=3 image: minio/minio #镜像名称以及版本 #限制docker容器的内存 deploy: resources: limits: memory: 1G restart: always #重启docker后该容器也重启 container_name: minio #容器名称 environment: TZ: Asia/Shanghai MINIO_ACCESS_KEY: admin MINIO_SECRET_KEY: admin volumes: - ./data:/data ports: - 9000:9000 - 9090:9090 #本地端口号与容器内部端口号 command: server /data --console-address ":9090" -address ":9000"RabbitMQdocker-compose.ymlversion: "3.8" services: rabbitmq: image: rabbitmq:3.12.8-management #镜像名称以及版本 #限制docker容器的内存 deploy: resources: limits: memory: 1G restart: always #重启docker后该容器也重启 container_name: rabbitmq #容器名称 environment: TZ: Asia/Shanghai ports: - 5672:5672 - 15672:15672 #本地端口号与容器内部端口号Typechodocker-compose.ymlversion: "3.8" services: nginx-typecho: image: 80x86/typecho #镜像名称以及版本 #限制docker容器的内存 deploy: resources: limits: memory: 1G restart: always #重启docker后该容器也重启 container_name: nginx-typecho #容器名称 environment: TZ: Asia/Shanghai ports: - 81:80 #本地端口号与容器内部端口号 volumes: #指定挂载目录 - ./data:/dataNginxdocker-compose.ymlversion: "3.8" services: nginx: image: nginx:1.25 #镜像名称以及版本 #限制docker容器的内存 deploy: resources: limits: memory: 2G restart: always #重启docker后该容器也重启 container_name: nginx #容器名称 environment: TZ: Asia/Shanghai ports: - 80:80 #本地端口号与容器内部端口号 volumes: #指定挂载目录 - ./conf/default.conf:/etc/nginx/conf.d/default.conf - ./html:/usr/share/nginx/htmldefault.confserver { listen 80; listen [::]:80; server_name localhost; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }SkyWalkingjava-agenthttps://mirrors.cloud.tencent.com/apache/skywalking/java-agent/9.1.0/java服务启动vm参数-javaagent:D:\env\skywalking-agent\skywalking-agent.jar -Dskywalking.agent.service_name=ruoyi-system -Dskywalking.collector.backend_service=localhost:11800docker-compose.ymlversion: "3.8" services: elasticsearch: image: elasticsearch:6.8.1 container_name: elasticsearch-6.8.1 restart: always ports: - 9200:9200 environment: discovery.type: single-node #es单机模式 TZ: Asia/Shanghai #时区设置 TAKE_FILE_OWNERSHIP: true #解决 volumes 挂载权限问题 ES_JAVA_OPTS: -Xms256m -Xmx256m ##jvm内存分配为256MB ulimits: memlock: soft: -1 hard: -1 volumes: - ./elasticsearch/data:/usr/share/elasticsearch/data oap: image: apache/skywalking-oap-server:8.5.0-es6 container_name: skywalking-oap-8.5.0 depends_on: - elasticsearch links: - elasticsearch restart: always ports: - 11800:11800 - 12800:12800 environment: SW_STORAGE: elasticsearch SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200 SW_HEALTH_CHECKER: default SW_TELEMETRY: prometheus healthcheck: test: ["CMD", "./bin/swctl", "ch"] interval: 30s timeout: 10s retries: 3 start_period: 40s ui: image: apache/skywalking-ui:8.5.0 container_name: skywalking-ui-8.5.0 depends_on: - oap links: - oap restart: always ports: - 8888:8080 environment: SW_OAP_ADDRESS: oap:12800Nacosdocker-compose.ymlversion: "3.8" services: mysql: image: mysql:8.1 #镜像名称以及版本 #限制docker容器的内存 deploy: resources: limits: memory: 1G restart: always #重启docker后该容器也重启 container_name: mysql8 #容器名称 environment: MYSQL_ROOT_PASSWORD: root #指定用户密码 TZ: Asia/Shanghai ports: - 3306:3306 #本地端口号与容器内部端口号 volumes: #指定挂载目录 - ./data:/var/lib/mysql - ./conf/my.cnf:/etc/mysql/my.cnf networks: - mysql_nacos_network healthcheck: test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ] interval: 5s timeout: 10s retries: 10 nacos: image: nacos/nacos-server:v2.3.0 container_name: nacos-standalone env_file: - ./nacos-env/nacos-standlone-mysql.env volumes: - ./standalone-logs/:/home/nacos/logs ports: - "8848:8848" - "9848:9848" restart: always networks: - mysql_nacos_network depends_on: mysql: condition: service_healthy networks: mysql_nacos_network: driver: bridgenacos-standlone-mysql.envNACOS_CORE_AUTH_ENABLED=true PREFER_HOST_MODE=hostname MODE=standalone SPRING_DATASOURCE_PLATFORM=mysql MYSQL_SERVICE_HOST=mysql8 MYSQL_SERVICE_DB_NAME=nacos MYSQL_SERVICE_PORT=3306 MYSQL_SERVICE_USER=root MYSQL_SERVICE_PASSWORD=root MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true NACOS_AUTH_IDENTITY_KEY=nacos NACOS_AUTH_IDENTITY_VALUE=nacos NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789my.cnf使用默认的配置即可Postgresdocker-compose.ymlservices: postgres: image: postgres:14 #镜像名称以及版本 #限制docker容器的内存 deploy: resources: limits: memory: 1G # restart: always #重启docker后该容器也重启 container_name: postgres #容器名称 environment: POSTGRES_PASSWORD: postgres volumes: - ./data:/var/lib/postgresql/data ports: - 5432:5432
安装Docker安装帮助文档# 1. 卸载旧的版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine # 2. 需要的安装包 yum install -y yum-utils # 3. 设置镜像仓库 sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # 默认是国外的 sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 推荐使用阿里云镜像 # 更新软件包索引 yum makecache fast # 4. 安装docker docker-ce 社区 ee 企业版 sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin # 5. 启动docker systemctl start docker # 6. 查看docker是否安装成功 docker version# 7. hello-world docker run hello-world# 8. 查看一下下载的这个 hello-world镜像 [root@centos-liunx-7 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 12 months ago 13.3kB了解: 卸载docker# 1. 卸载依赖 sudo yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin # 2. 删除资源 sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd # /var/lib/docker docker的默认工作路径阿里云镜像加速打开阿里云,找到镜像容器服务找到镜像加速器配置使用sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://7ux125dt.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker回顾HelloWorld流程底层原理Docker是怎么工作的?Docker是一个Client - Server结构的系统,Docker的守护进程运行在主机上.通过Scoket从客户端访问!Docker为什么比VM快?Docker有着比虚拟机更少的抽象层docker利用的是宿主机的内核, vm需要Guest OS所以说,新建一个容器的时候,docker不需要向虚拟机一样重新加载一个操作系统内核,避免引导.虚拟机是加载Guest OS,分钟级别的,而docker是利用 宿主机的操作系统,省略了这个复杂的过程,秒级!Docker的常用命令帮助命令docker version # 显示docker的版本信息 docker info # docker的系统信息,包裹镜像和容器的数量 docker 命令 --help # 万能命令帮助文档的地址: https://docs.docker.com/engine/reference/commandline/docker/镜像命令docker images 查看所有本地的主机上的镜像[root@centos-liunx-7 /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 12 months ago 13.3kB # 解释 REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的ID CREATE 镜像的创建时间 SIZE 镜像的大小 # 可选项 -a, --all 显示所有镜像 -q, --quiet 只显示镜像的IDdocker search 镜像的搜索命令# docker search 镜像名称 [root@centos-liunx-7 /]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 13234 [OK] mariadb MariaDB Server is a high performing open sou… 5062 [OK] phpmyadmin phpMyAdmin - A web interface for MySQL and M… 640 [OK] percona Percona Server is a fork of the MySQL relati… 588 [OK] bitnami/mysql Bitnami MySQL Docker Image 77 [OK] # 可选项 -f stars=3000 # 搜索出来的镜像就是stars大于3000的 [root@centos-liunx-7 /]# docker search mysql -f stars=3000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 13234 [OK] mariadb MariaDB Server is a high performing open sou… 5062 [OK] 下载镜像 docker pull# 下载镜像 docker pull 镜像名[:tag] [root@centos-liunx-7 /]# docker pull mysql Using default tag: latest # 如果不写 tag,默认就是latest latest: Pulling from library/mysql 72a69066d2fe: Pull complete # 分层下载,docker image的核心 联合文件系统 93619dbc5b36: Pull complete 99da31dd6142: Pull complete 626033c43d70: Pull complete 37d5d7efb64e: Pull complete ac563158d721: Pull complete d2ba16033dad: Pull complete 688ba7d5c01a: Pull complete 00e060b6d11d: Pull complete 1c04857f594f: Pull complete 4d7cfa90e6ea: Pull complete e0431212d27d: Pull complete Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 签名 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest # 真实地址 # 等价于它 docker pull mysql 等价于 docker pull docker.io/library/mysql:latest # 指定版本下载 [root@centos-liunx-7 /]# docker pull mysql:5.7 5.7: Pulling from library/mysql 72a69066d2fe: Already exists 93619dbc5b36: Already exists 99da31dd6142: Already exists 626033c43d70: Already exists 37d5d7efb64e: Already exists ac563158d721: Already exists d2ba16033dad: Already exists 0ceb82207cd7: Pull complete 37f2405cae96: Pull complete e2482e017e53: Pull complete 70deed891d42: Pull complete Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7docker rmi 删除镜像[root@centos-liunx-7 /]# docker rmi -f 镜像ID # 删除指定的容器 [root@centos-liunx-7 /]# docker rmi -f 镜像ID 容器ID 容器ID # 删除多个容器 [root@centos-liunx-7 /]# docker rmi -f $(docker images -aq) # 删除全部的容器容器命令说明: 我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习docker pull centos新建容器并启动docker run [可选参数] image # 参数说明 --name="Name" 容器名字 tomcat01 tomcat02,用来区分容器 -d 后台方式运行 -it 使用交互方式运行 -p 指定容器端口 -p 8080:8080 -p ip:主机端口:容器端口 -p 主机端口:容器端口 (常用) -p 容器端口 容器端口 -P 随机指定端口 # 测试,启动并进入容器 [root@centos-liunx-7 /]# docker run -it centos /bin/bash [root@ab7ab1d9dc9b /]# ls # 查看容器内的centos,基础版本,很多命令是不完善的 bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 从容器中退回主机 [root@ab7ab1d9dc9b /]# exit exit [root@centos-liunx-7 /]# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var列出所有的运行中的容器# docker ps 命令 # 列出当前正在运行的容器 -a # 列出当前正在运行的容器+带出历史运行过的容器 -n=? # 显示最近创建的容器 -q # 只显示容器的编号 [root@centos-liunx-7 /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ab7ab1d9dc9b centos "/bin/bash" 6 minutes ago Exited (0) 2 minutes ago frosty_feistel e19001022375 feb5d9fea6a5 "/hello" About an hour ago Exited (0) About an hour ago romantic_antonelli 退出容器exit # 直接容器停止并退出 ctrl + p + q # 容器不停止退出删除容器docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f docker rm -f $(docker ps -aq) # 删除所有的容器 docker ps -a -q|xargs docker rm # 删除所有的容器启动和停止容器的操作docker start 容器ID # 启动容器 docker restart 容器ID # 重启容器 docker stop 容器ID # 停止当前正在运行的容器 docker kill 容器ID # 强制停止当前容器常用其他命令后台启动容器# 命令 docker run -d 镜像名! [root@centos-liunx-7 ~]# docker run -d centos # 问题docker ps,发现 centos 停止了 # 常见的坑: docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止 # nginx,容器启动后,发现自己没有提供服务,就会立刻定制,就是没有程序了查看日志命令docker logs -f -t -n 条数 容器ID -t 显示日期+时间 -n 10 显示最近10条查看容器中的进程信息 ps# 命令 docker top 容器ID [root@centos-liunx-7 ~]# docker top 293933b1a937 UID PID PPID C STIME TTY TIME CMD root 5269 5251 0 11:46 pts/0 00:00:00 /bin/bash [root@centos-liunx-7 ~]查看镜像的元数据# 命令 docker inspect 容器id # 测试 [root@centos-liunx-7 ~]# docker inspect 293933b1a937 [ { "Id": "293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23", "Created": "2022-10-02T03:46:19.579531063Z", "Path": "/bin/bash", "Args": [], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 5269, "ExitCode": 0, "Error": "", "StartedAt": "2022-10-02T03:46:19.862987449Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6", "ResolvConfPath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/resolv.conf", "HostnamePath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/hostname", "HostsPath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/hosts", "LogPath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23-json.log", "Name": "/romantic_cohen", "RestartCount": 0, "Driver": "overlay2", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": [ "d959bc38ccb4a8f5f7f048538a5683e29f9091d6c7a2662b8afd0e207fdc93f8", "9b3b78add31342988b556a4f1d50dab6e343e01922bf2d0d630cf57552c21d21" ], "HostConfig": { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} }, "NetworkMode": "default", "PortBindings": {}, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "CgroupnsMode": "host", "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "private", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DeviceRequests": null, "KernelMemory": 0, "KernelMemoryTCP": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": [ "/proc/asound", "/proc/acpi", "/proc/kcore", "/proc/keys", "/proc/latency_stats", "/proc/timer_list", "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", "/sys/firmware" ], "ReadonlyPaths": [ "/proc/bus", "/proc/fs", "/proc/irq", "/proc/sys", "/proc/sysrq-trigger" ] }, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3-init/diff:/var/lib/docker/overlay2/d60d4305d3caf9a7a1b2b1a4f8cea9d0972e6672ea996ea443730d0f414b2147/diff", "MergedDir": "/var/lib/docker/overlay2/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3/merged", "UpperDir": "/var/lib/docker/overlay2/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3/diff", "WorkDir": "/var/lib/docker/overlay2/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { "Hostname": "293933b1a937", "Domainname": "", "User": "", "AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "Tty": true, "OpenStdin": true, "StdinOnce": true, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/bash" ], "Image": "centos", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20210915", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS" } }, "NetworkSettings": { "Bridge": "", "SandboxID": "da5bbf74792f2eb5e8ad6160bb67301616f79f8f2424b19171d7ee5e8582553d", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/da5bbf74792f", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "a274ca41faf2a0e7dae8088cb5c78862a090d39535ec91c4eae676837be0a3a7", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "1db544b9e9042fcde5347650f180de98bc17f8499545c386ccc2bd19507e420f", "EndpointID": "a274ca41faf2a0e7dae8088cb5c78862a090d39535ec91c4eae676837be0a3a7", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ] [root@centos-liunx-7 ~]# 进入当前正在运行的容器# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置 # 命令 docker exec -it 容器id bashShell # 测试 [root@centos-liunx-7 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 293933b1a937 centos "/bin/bash" 22 minutes ago Up 22 minutes romantic_cohen [root@centos-liunx-7 ~]# docker exec -it 293933b1a937 /bin/bash [root@293933b1a937 /]# ps PID TTY TIME CMD 50 pts/3 00:00:00 bash 64 pts/3 00:00:00 ps [root@293933b1a937 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@293933b1a937 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 03:46 pts/0 00:00:00 /bin/bash root 20 0 0 04:01 pts/1 00:00:00 /bin/bash root 36 0 0 04:02 pts/2 00:00:00 /bin/bash root 50 0 0 04:08 pts/3 00:00:00 /bin/bash root 66 50 0 04:08 pts/3 00:00:00 ps -ef # 方式二 docker attach 容器ID # 测试 [root@centos-liunx-7 ~]# docker attach 293933b1a937 正在执行当前的代码... # docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用) # docker attach # 进入容器正在执行的终端,不会启动新的进程从容器内拷贝文件到主机上docker cp 容器id:容器内路径 目的的主机路径 # 测试 [root@centos-liunx-7 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 293933b1a937 centos "/bin/bash" 2 hours ago Up 1 second romantic_cohen # 进入当前正在运行的容器 [root@centos-liunx-7 ~]# docker attach 293933b1a937 # 创建一个文件 [root@293933b1a937 /]# touch test.java # 查看目录 [root@293933b1a937 /]# ls bin etc lib lost+found mnt proc run srv test.java usr dev home lib64 media opt root sbin sys tmp var # 退出容器 [root@293933b1a937 /]# exit exit # 从容器中拷贝文件到宿主机目录中 [root@centos-liunx-7 ~]# docker cp 293933b1a937:/test.java / [root@centos-liunx-7 ~]# cd / # 查看宿主机目录 [root@centos-liunx-7 /]# ls bin dev home lib64 mnt proc run srv test.java usr boot etc lib media opt root sbin sys tmp var [root@centos-liunx-7 /]# # 拷贝是一个手动过程,未来我们使用 -v卷的技术,可以实现将宿主机的文件拷贝到容器中：docker cp 宿主机路径 容器编号:容器路径docker cp /javadxy/software/apache-tomcat-8.5.20/webapps tomcat1:/usr/local/tomcat/重要学习方式: 将上课的内容自己敲一遍,记录笔记作业练习部署Nginx# 1. 搜索镜像 search #推荐使用hub.docker.com搜索镜像,docker hub中有详细的帮助文档和命令 [root@centos-liunx-7 ~]# docker search nginx # 2. 下载镜像 [root@centos-liunx-7 ~]# docker pull nginx # 3. 通过镜像运行容器 [root@centos-liunx-7 ~]# docker run -d -it --name nginx01 -p 5000:80 nginx -d 后台运行 -it 交互模式 --name 给容器命名 -p 宿主机端口:容器端口 指定端口号 # 4. 验证nginx是否启动成功 浏览器访问 宿主IP:5000如果是使用阿里云服务器的需要把阿里云5000端口放行思考: 我们每次需要修改Nginx配置文件的时候都需要进入容器去修改,可以不可以直接在宿主机中直接修改一个文件,容器中的配置文件也会跟着改变?部署Tomcat# 官方的使用 $ docker run -it --rm tomcat:9.0 --rm # 在退出tomcat之后会将这个容器删除,一般用于测试 # 1. 搜索镜像 [root@centos-liunx-7 ~]# docker search tomcat # 2. 下载镜像 [root@centos-liunx-7 ~]# docker pull tomcat:8.5 # 指定版本号下载 # 3. 通过镜像运行容器 [root@centos-liunx-7 ~]# docker run -d --name tomcat02 -p 8081:8080 tomcat:8.5 # 4. 测试Tomcat是否启动成功 浏览器访问 宿主IP:8081 # 发现问题,页面404,少了linux命令 # 因为阿里镜像的原因,它保证这个镜像可运行,保证镜像最小 # 页面404是因为webapps文件夹内没有文件 # 将webapps.dist中的文件拷贝到webapps中,在刷新网页 [root@centos-liunx-7 ~]# docker exec -it tomcat02 /bin/bash root@492a85fba570:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@492a85fba570:/usr/local/tomcat# cd webapps.dist/ root@492a85fba570:/usr/local/tomcat/webapps.dist# ls ROOT docs examples host-manager manager root@492a85fba570:/usr/local/tomcat/webapps.dist# cd ../ root@492a85fba570:/usr/local/tomcat# cd webapps root@492a85fba570:/usr/local/tomcat/webapps# ls root@492a85fba570:/usr/local/tomcat/webapps# cd ../ root@492a85fba570:/usr/local/tomcat# cp -r webapps.dist/* webapps root@492a85fba570:/usr/local/tomcat# cd webapps root@492a85fba570:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager root@492a85fba570:/usr/local/tomcat/webapps思考问题: 我们每次部署Tomcat项目的时候也要进入到容器内部去部署项目,十分的麻烦.有没有一种技术,修改宿主机文件,容器内部的文件自动同步?可视化portainer(先用这个)docker run -d -p 8088:9000 \ --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainerRancher(CI/CD再用)Portainer使用ip:8088进入设置密码选择本地进入面板镜像原理之分层理解我们从Docker Hub下载的镜像是只读的在使用镜像启动容器之后,我们在基于容器之后的操作(比如修改了某些文件),可以理解成在容器上面加了一层,你的每一个操作,都是在这个容器之上叠加,这个就是镜像之联合文件系统镜像原理之文件联合系统容器都是基于宿主机的内核启动的比如我们下载一个mysql(有6层)我们在下载一个redis,可能redis也有6层,而redis的前两层和刚才下载mysql的前两层是一样的Docker 就会复用mysql的前两层文件就不会再去下载Commit镜像## 使用Tomcat镜像启动容器 [root@centos-liunx-7 ~]# docker run -it -d -p 8080:8080 tomcat:8.5 ## 发现webapps中没有文件 [root@centos-liunx-7 ~]# docker exec -it 2883d64efa26 /bin/bash root@2883d64efa26:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@2883d64efa26:/usr/local/tomcat# cd webapps root@2883d64efa26:/usr/local/tomcat/webapps# ls ## 将webapps.dist中的文件复制到webapps中 root@2883d64efa26:/usr/local/tomcat/webapps# cd ../ root@2883d64efa26:/usr/local/tomcat# cp -r webapps.dist/* webapps root@2883d64efa26:/usr/local/tomcat# ls webapps ROOT docs examples host-manager manager root@2883d64efa26:/usr/local/tomcat# ## 这个时候我们以后都想使用这个镜像运行,就要提交镜像 [root@centos-liunx-7 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2883d64efa26 tomcat:8.5 "catalina.sh run" 5 minutes ago Up 5 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp kind_swanson ## 提交镜像 ## docker commit -m="提交的消息 webapps app" -a="作者" 容器id 容器名称:版本号 [root@centos-liunx-7 ~]# docker commit -m="add webapps app" -a="yiyu" 2883d64efa26 tomcat:1.0 sha256:53fb07d89492a1afd6fe1097252122e2b6a1a658adaa9157aecef0bbe4687e3b [root@centos-liunx-7 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat 1.0 53fb07d89492 2 seconds ago 683MB nginx latest 605c77e624dd 9 months ago 141MB tomcat 8.5 2d2bccf89f53 9 months ago 678MB tomcat latest fb5657adc892 9 months ago 680MB mysql latest 3218b38490ce 9 months ago 516MB centos latest 5d0da3dc9764 12 months ago 231MB portainer/portainer latest 580c0e4e98b0 18 months ago 79.1MB [root@centos-liunx-7 ~]# -a="作者" -m="提交的消息"这个时候我们就可以使用提交好的镜像去启动一个容器,而且启动后的容器中的tomcat是有主页面的容器数据卷什么是容器数据卷?当我们使用mysql镜像创建了一个容器,之后把容器删除之后,那么我们容器中的数据就丢失了.这个时候我们可以使用数据卷,将容器内的数据和本地数据连接起来,当容器中数据改变或者本地数据改变的时候,它们都会自动同步使用容器数据卷## 命令 docker run -d -it -v 宿主机目录:容器内部目录 [root@centos-liunx-7 home]# docker run -d -it -v /home/ceshi:/home centos ## 查看是否挂载成功 [root@centos-liunx-7 home]# docker inspect 容器id "Mounts": [ { "Type": "bind", "Source": "/home/ceshi", "Destination": "/home", "Mode": "", "RW": true, "Propagation": "rprivate" } ], # 如果元数据中Mounts数组中有数据,表示挂载成功了 # 测试 # 在容器内部home目录下创建的文件,在宿主机/home/ceshi目录也会同步出来 # 反之,在/home/ceshi目录下创建或操作的文件,也会同步到容器内部注意: 就算容器被关闭,在宿主机/home/ceshi目录下创建的文件依旧会同步到容器内部实战: 安装MySQL# 下载镜像 docker pull mysql # 启动 # 官方的启动命令 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag # 我们的启动命令 -it 交互模式 -d 后台运行 -v 数据卷挂载 -e 环境配置 --name 给容器命名 [root@centos-liunx-7 ceshi]# docker run -it -d -p 3310:3306 -v /home/mysql/data:/var/lib/mysql -v /home/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql使用Navicat连接MYSQL并创建一个数据库,linux中的数据也会随之改变当我们删除容器时,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化具名挂载和匿名挂载# 命令 具名挂载 # docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx nginx -P 随机端口 [root@centos-liunx-7 data]# docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx nginx df0f46eecd648da7709792285d70b58146c8885aab22e4bf8bd585b5e9208ed4 [root@centos-liunx-7 data]# docker volume ls DRIVER VOLUME NAME local 7bd9c653cd464bd8dc902b0f70b97d09a3ce6d0db5de9ac874c6072a877b8920 local 51b6c469889451450ba07cf2a781dc1c34955a0c3f3e3aa251614c41f7319e85 local 735e477cfb34b3113a458940dc3ba47db0b3ccb73d2be80f24f4bef7488115a7 local b4e659a7be46bf56c07f131c647a69b9bb3d568bbe52b3ee8fc8495f31d0a1c0 local e29d1ac89192283e4ffc5c0e9d4bf8ac19740a1c8655be3a80673bde3e6d199a local juming-nginx # 查看卷 docker volume ls # 查看卷数据 docker volume inspect 卷名称 [root@centos-liunx-7 data]# docker volume inspect juming-nginx [ { "CreatedAt": "2022-10-02T21:21:28+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", "Name": "juming-nginx", "Options": null, "Scope": "local" } ] [root@centos-liunx-7 data]# # 如何查看是具名挂载和匿名挂载,还是指定路径挂载 -v 卷名称:容器内路径 # 具名挂载 -v 容器内路径 # 匿名挂载 -v 宿主机路径:容器内路径 # 指定路径挂载默认的挂载路径为 /var/lib/docker/volumes/xxxxx/_data扩展docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:ro nginx docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:rw nginx # ro readonly #只读 # rw readwrite #可读可写 # 在只读的情况下不能在容器内容修改文件,只能在容器外修改 # 默认是rw(可读可写)初识DockerfileDockerfile就是用来构建docker镜像的构建文件!可以理解成一个命令脚本!通过这个脚本可以生成镜像,镜像是一层一层的,脚本中一个个的命令,每个命令都是一层!# 创建一个dockerfile文件,名字可以随机,建议 Dockerfile # 文件中的内容 命令(是大写的) FROM centos VOLUME ["volume1","volume2"] CMD echo "----end----" CMD /bin/bash命令 构建[root@centos-liunx-7 docker-volumn-file]# docker build -f dockerfile1 -t yiyu/centos:1.0 . -f Dockerfile文件的路径 -t 镜像名称:版本号 .构建到当前docker使用我们自己构建的镜像创建容器[root@centos-liunx-7 docker-volumn-file]# docker run -it 9662d35446d3 /bin/bash [root@86f89bc561de /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume1 volume2 # 发现多了2个文件夹,这两个文件夹就是我们在构建镜像时创建的数据卷# 使用命令 docker inspect 容器id 查看容器元数据发现已经自动挂载好了(匿名挂载)这就实现了我们在创建容器时自动挂载数据卷,而不用使用 -v 命令手动挂载数据卷容器# 命令 --volumes-from 父容器id使用刚才构建的镜像创建两个容器并在第二个容器数据卷中创建文件,第一个容器中的数据卷会自动同步拷贝机制多个mysql实现数据共享[root@centos-liunx-7 ceshi]# docker run -it -d -p 3310:3306 -v /var/lib/mysql -v /etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql [root@centos-liunx-7 ceshi]# docker run -it -d -p 3310:3306 --volumes-from mysql01 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 mysql # 这个时候,可以实现两个容器数据共享DockerFileDockerFile的指令FROM # 基础镜像,一切从这里开始构建 MAINTAINER # 镜像是谁写的,姓名+邮箱 RUN # 镜像构建的时候需要运行的命令 ADD # 步骤: 添加其他镜像到DockerFile中. 压缩包 WORKDIR # 镜像的工作目录 VOLUME # 挂载的目录 EXPOSE # 暴露端口配置 CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令 ONBUILD # 当构建一个被继承 DockerFIle 这个时候会运行 ONBUILD 的指令. 触发指令 COPY # 类似ADD, 将我们的文件拷贝到镜像中 ENV # 构建的时候设置环境变量!实战测试创建自己的centos[root@centos-liunx-7 dockerfile-work]# cat mydockerfile-centos FROM centos MAINTAINER yiyu<318334629@qq.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "----end----" CMD /bin/bash #构建命令 docker build -f dockerfile文件路径 -t 镜像名称:[tag] .遇到问题: vim和net-tools安装失败# 运行自己构建的centos [root@centos-liunx-7 dockerfile-work]# docker run -it mycentos:0.1 [root@5a47d68eaf04 local]# pwd /usr/local [root@5a47d68eaf04 local]# ls bin etc games include lib lib64 libexec sbin share src # 可以看到运行后的工作路径是/usr/local,说明上面写的命令是没问题的实战:Tomcat镜像准备镜像文件 tomcat 压缩包,jdk的压缩包编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件FROM centos MAINTAINET yiyu<318334629@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u341-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.67.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_341 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.67 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.67 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_BASH/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.67/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.67/bin/ logs/catalina.ou构建镜像# docker build -t diytomcat .启动镜像访问测试发布项目(由于做了卷挂载,我们之前在本地编写项目就可以发布了)<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0"> </web-app><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> hello,yiyu Hello World! <% System.out.println("-----my test web logs-----"); %> 发现: 项目部署成功,可以直接访问!我们以后开发的步骤: 需要掌握Dockerfile的编写! 我们之后的一切都是使用docker镜像来发布运行发布自己的镜像Dockerhub地址 https://hub.docker.com/ 注册自己的账号确保账号可以登录在我们服务器上提交自己的镜像[root@centos-liunx-7 tomcatlogs]# docker login --help Usage: docker login [OPTIONS] [SERVER] Log in to a Docker registry. If no server is specified, the default is defined by the daemon. Options: -p, --password string Password --password-stdin Take the password from stdin -u, --username string Username [root@centos-liunx-7 tomcatlogs]# [root@centos-liunx-7 tomcatlogs]# docker login -u chengxuyi Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded登录完毕后就可以提交镜像了,就是一步 docker push# push自己的镜像到服务器上 [root@centos-liunx-7 tomcatlogs]# docker push diytomcat Using default tag: latest The push refers to repository [docker.io/library/diytomcat] 3b80368c27b7: Preparing a46e380f6b0d: Preparing 009bcb6b88ee: Preparing 74ddd0ec08fa: Preparing denied: requested access to the resource is denied # 拒绝 # push镜像的问题 [root@centos-liunx-7 tomcatlogs]# docker push chengxuyi/diytomcat:11 The push refers to repository [docker.io/chengxuyi/diytomcat] An image does not exist locally with the tag: chengxuyi/diytomcat # 解决,增加一个 tag [root@centos-liunx-7 tomcatlogs]# docker tag 3962139fb78c chengxuyi/tomcat:0.9 # docker push上去即可! 自己发布的镜像尽量带上版本号 [root@centos-liunx-7 tomcatlogs]# docker push chengxuyi/tomcat:0.9 The push refers to repository [docker.io/chengxuyi/tomcat] 3b80368c27b7: Pushing 6.17MB/16.11MB a46e380f6b0d: Pushing 13.09MB/369.8MB 009bcb6b88ee: Pushed 74ddd0ec08fa: Pushing 13.13MB/231.3MB提交的时候也是安装镜像的层级来进行提交的阿里云镜像服务上登录阿里云找到容器镜像服务创建命名空间创建容器镜像仓库浏览阿里云docker push registry.cn-hangzhou.aliyuncs.com/chengxuyi/yiyu:[镜像版本号]解决阿里云镜像无法push: CSDN小结Docker网络理解Docker网络0清空所有环境测试三个网络# 问题: docker 是如何处理容器网络访问的? # 查看容器的内部网络地址 ip addr原理我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker就会有一个网卡docker0,桥接模式,使用的技术是 evth-pair 技术可以把docker的主网卡想成一个路由器,而每使用docker启动一个容器,docker就给给这个容器分配一个内网的IP地址每启动一个容器,就会多一对网卡# 我们发现这个容器带来的网卡,都是一对对的 # evth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连 # 正因为有这个特效, evth-pair 充当一个桥梁,连接各种虚拟网络设备的 # PoenStac,Docker容器之间的连接,OVS的连接,都是使用 evth-pair 技术我们来测试下centos01和centos02是否可以ping通![root@centos-liunx-7 /]# docker exec -it centos01 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 84: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever [root@centos-liunx-7 /]# docker exec -it centos02 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 86: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever [root@centos-liunx-7 /]# docker exec -it centos01 ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.129 ms 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.085 ms 64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.102 ms 64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.104 ms 64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.067 ms # 结论: 容器和容器之间是可以互相ping通的结论: centos01 和 centos02 是公用一个路由器, Docker0所有的容器不指定网络的情况下,都是 docker0 路由的,docker会给我们的容器分配一个默认可以的IP小结DOcker 使用的是Linux的桥接,宿主机中是一个Docker容器的网桥 docker0Docker中的所有的网络接口都是虚拟的.虚拟的转发效率高!只要容器删除,对应的网桥一对就没了--link思考一个场景,我们编写了一个微服务,database url=ip, 项目不重启,数据ip换掉了,我们希望可以处理这个问题,可以通过名字来进行访问容器![root@centos-liunx-7 /]# docker exec -it tomcat02 ping tomcat01 Error: No such container: tomcat02 # 如何可以解决呢? # 通过--link 就可以解决了网络联通问题 [root@centos-liunx-7 /]# docker run -d -it -P --name centos03 --link centos02 centos 1fccd0e0c5a2a1ea4886003d1a0021ea45fa9f1a93b0e0d263655da83f17b056 [root@centos-liunx-7 /]# docker exec -it centos02 ping centos01 ping: centos01: Name or service not known [root@centos-liunx-7 /]# docker exec -it centos03 ping centos02 PING centos02 (172.17.0.3) 56(84) bytes of data. 64 bytes from centos02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.098 ms 64 bytes from centos02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.217 ms 64 bytes from centos02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.076 ms # 反向可以ping通吗? [root@centos-liunx-7 /]# docker exec -it centos02 ping centos03 ping: centos03: Name or service not known其实这个centos03就是在本地配置了centos02# 查看 hosts 配置,在这里原理发现! [root@centos-liunx-7 /]# docker exec -it centos03 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 centos02 080b56a86172 172.17.0.4 1fccd0e0c5a2本质探究: --link就是在我们hosts配置中增加了一个172.17.0.3 centos02 080b56a86172我们现在玩Docker已经不建议使用--link了!自定义网络!不使用docker0docker0问题:他不支持容器名连接访问!自定义网络查看所有的docker网络网络模式bridge: 桥接模式 docker(默认,自己创建也是用brideg模式)none: 不配置网络host: 和宿主机共享网络container: 容器内网络连通(用的少!局限性很大)测试# 我们直接启动的命令 --net bridge ,而这个就是我们的docker0 docker run -d -P --name centos01 --net bridge centos # docker0的特点: 默认,域名不能访问,--link可以打通连接 # 我们 可以自定义一个网络 # --driver bridge # --subnet 192.168.0.0/16 192.168.0.2 192.168.255.255 # --gateway 192.168.0.1 [root@centos-liunx-7 /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 2eda7ce36f8f3b6c6ac6af7ae95fc593367bd9d48d637110dbbce437ac0440e7 [root@centos-liunx-7 /]# docker network ls NETWORK ID NAME DRIVER SCOPE b3f10c44674d bridge bridge local 89c2b174693d host host local 2eda7ce36f8f mynet bridge local bf454ee5fa23 none null local [root@centos-liunx-7 /]# docker run -d -it -P --name centos-net-01 --net mynet centos 37e9334cd00053f9fcc003e58bb1e811fc11bdc9e0517301ef1920210d94fe77 [root@centos-liunx-7 /]# docker run -d -it -P --name centos-net-02 --net mynet centos 0f72e3f2d724eb2ba2e81e3ec6c4af1f1d364163e01e586a8ced56b2e8b982d0 [root@centos-liunx-7 /]# docker network inspect "docker network inspect" requires at least 1 argument. See 'docker network inspect --help'. Usage: docker network inspect [OPTIONS] NETWORK [NETWORK...] Display detailed information on one or more networks [root@centos-liunx-7 /]# docker network inspect mynet [ { "Name": "mynet", "Id": "2eda7ce36f8f3b6c6ac6af7ae95fc593367bd9d48d637110dbbce437ac0440e7", "Created": "2022-10-04T15:05:56.551606092+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", "Gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "0f72e3f2d724eb2ba2e81e3ec6c4af1f1d364163e01e586a8ced56b2e8b982d0": { "Name": "centos-net-02", "EndpointID": "f42ecdc2792113040e91efaca8ebe68c0982cb9e30ccff51a36c2c0219cd8ca5", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "37e9334cd00053f9fcc003e58bb1e811fc11bdc9e0517301ef1920210d94fe77": { "Name": "centos-net-01", "EndpointID": "7bb99f5c54a3aa0a71907a0dfdcecfd9f3166a5f80e3509b9e0ad6d0907d864c", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] # 再次测试ping连接 [root@centos-liunx-7 /]# docker exec -it centos-net-01 ping centos-net-02 PING centos-net-02 (192.168.0.3) 56(84) bytes of data. 64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.080 ms 64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.065 ms 64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.064 ms # 现在不使用--link也可以ping名字了我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!好处: redis - 不同的集群使用不同的网络,保证集群是安全健康的mysql - 不同的集群使用不同的网络,保证集群是安全健康的网络连通# 测试打通 centos03 - mynet [root@centos-liunx-7 /]# docker network connect mynet 56d4731f695f [root@centos-liunx-7 /]# docker exec -it centos03 ping centos-net-01 PING centos-net-01 (192.168.0.2) 56(84) bytes of data. 64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.241 ms 64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.070 ms 64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.088 ms # 连通之后就是将centos03 放到了 mynet 网络下 # 一个容器两个ip地址! 结论: 假设要跨网络操作别人,就需要使用docker network connect 连通!实战: 部署Redis集群shell脚本# 创建网卡 docker network create redis --subnet 172.38.0.0/16 # 通过脚本创建六个redis配置 for port in $(seq 1 6); \ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >/mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ -v /mydata/redis/node-1/data:/data \ -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ -v /mydata/redis/node-6/data:/data \ -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf # 创建集群 /data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:63 79 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 M: e25f16e906ac90fe3e22475dcb7b7c1e51a3144e 172.38.0.11:6379 slots:[0-5460] (5461 slots) master M: a535292a5dfb31ce54f82828681d6b2472de3021 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master M: 5b79173ce1dfc1355e57bcfc36c59ea0490da47d 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master S: baa3ab92abe356b23ad485c3c64528b181ca8981 172.38.0.14:6379 replicates 5b79173ce1dfc1355e57bcfc36c59ea0490da47d S: 7fc66da4754d9d363d90e8e4248ced7c8ec094f4 172.38.0.15:6379 replicates e25f16e906ac90fe3e22475dcb7b7c1e51a3144e S: c4dda1ab836499e84a48b26f762226b7010fec52 172.38.0.16:6379 replicates a535292a5dfb31ce54f82828681d6b2472de3021 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join ... >>> Performing Cluster Check (using node 172.38.0.11:6379) M: e25f16e906ac90fe3e22475dcb7b7c1e51a3144e 172.38.0.11:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: baa3ab92abe356b23ad485c3c64528b181ca8981 172.38.0.14:6379 slots: (0 slots) slave replicates 5b79173ce1dfc1355e57bcfc36c59ea0490da47d M: a535292a5dfb31ce54f82828681d6b2472de3021 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: 5b79173ce1dfc1355e57bcfc36c59ea0490da47d 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: c4dda1ab836499e84a48b26f762226b7010fec52 172.38.0.16:6379 slots: (0 slots) slave replicates a535292a5dfb31ce54f82828681d6b2472de3021 S: 7fc66da4754d9d363d90e8e4248ced7c8ec094f4 172.38.0.15:6379 slots: (0 slots) slave replicates e25f16e906ac90fe3e22475dcb7b7c1e51a3144e [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. docker 搭建redis集群完成我们使用docker之后,所有的技术都会慢慢的变得简单起来SpringBoot微服务打包Docker镜像构建springboot项目打包应用编写dockerfile构建镜像发布运行以后我们使用了Docker之后,给别人交付的就是一个镜像即可!
Jenkins集成SonarQubeScanner在构建项目时对代码进行检查Jenkins安装SonarQubeScanner插件生成密钥：打开SonarQube服务端复制令牌配置SonarQube服务端类型选择Secret text，输入复制的令牌构建项目时添加SonarQubeScanner步骤重新构建在构建成功之后执行了SonarScanner命令进行检查SonarQube服务端也新增了一个检查
SonarQubeSonarQube（前身为Sonar）是一个开源的代码质量管理平台。它提供了一个集中的平台，用于对源代码进行静态代码分析、测量代码质量、跟踪技术债务、管理代码复杂性以及监控代码规范和安全性等方面的指标。SonarQube支持多种编程语言，包括Java、C/C++、C#、Python、JavaScript等，并提供了丰富的插件生态系统，以扩展和定制功能。SonarQube还提供了直观的仪表板和报告，用于可视化和监控代码质量的变化趋势。Docker形式安装SonarQube编写docker-compose.ymlversion: '3.1' services: db: image: postgres container_name: db ports: - 5432:5432 networks: - sonarnet environment: POSTGRES_USER: sonar POSTGRES_PASSWORD: sonar sonarqube: image: sonarqube:9.9-community container_name: sonarqube depends_on: - db ports: - 9000:9000 networks: - sonarnet environment: SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar SONAR_JDBC_USERNAME: sonar SONAR_JDBC_PASSWORD: sonar networks: sonarnet: driver: bridge启动命令：docker-compose up -dWindows启动失败查看SonarQube容器日志bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]启动失败解决办法：https://blog.csdn.net/qq_38680405/article/details/126700722浏览器打开端口为9000Maven与SonarQube集成修改Maven配置文件：settings.xml在profiles标签中新增SonarQube配置信息并激活配置<profiles> <profile> <id>sonar</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <sonar.login>admin</sonar.login> <sonar.password>123456</sonar.password> <sonar.host.url>http://localhost:9000</sonar.host.url> </properties> </profile> </profiles> <activeProfiles> <activeProfile>sonar</activeProfile> </activeProfiles>在项目根目录运行：mvn sonar:sonar在SonarQube提供的可视化界面查看检查结果SonarScannerSonarScanner是SonarQube的命令行工具，用于将源代码发送到SonarQube服务器进行分析。它是一个独立的客户端工具，可以与SonarQube进行集成，以便在分析阶段捕获和处理代码。SonarScanner通过读取配置文件（如sonar-project.properties）或通过命令行参数传递配置信息，确定需要分析的项目和相关设置。它会扫描项目的源代码，执行静态代码分析，并将结果提交到SonarQube服务器进行处理和展示。SonarScanner支持多种构建工具和编程语言，包括Maven、Gradle、Ant、MSBuild等。它可以轻松地集成到持续集成（CI）和持续交付（CD）流程中，使开发团队能够在每次代码提交或构建时自动进行代码质量分析。下载地址：https://docs.sonarqube.org/latest/analyzing-source-code/scanners/sonarscanner/下载自己对应的操作系统文件命令行方式检查代码打开SonarScanner配置文件：sonar-scanner.properties更改后的文件内容为#Configure here general information about the environment, such as SonarQube server connection details for example #No information about specific project should appear here #----- Default SonarQube server # 对应sonarQube的url地址 sonar.host.url=http://localhost:9000 #----- Default source code encoding sonar.sourceEncoding=UTF-8 执行检查# 切换到SonarScanner目录 cd E:\environment\sonar-scanner-4.8.0.2856-windows\bin # 执行 ./sonar-scanner.bat -D sonar.java.binaries=./**/target -D sonar.source=./ -D sonar.login=sqa_684223ae6877050107f0b3e3368e72fc06759874 -D sonar.projectKey=bms-project -D sonar.projectBaseDir=E:\overload-working\bms-dianshang-project -D sonar.exclusions=RuoYi-Vue3/** # 注释 # sonar.java.binaries 编译后的class文件位置 # sonar.source 源码位置 # sonar.login token # sonar.projectKey 项目的Key # sonar.projectBaseDir 项目的基本路径 # sonar.exclusions 需要排除的文件夹或者文件
Jenkins教程Jenkins是一个开源的自动化服务器，用于实现软件开发过程中的持续集成和持续交付。它提供了一种灵活的方式来构建、测试和部署软件项目，以及监控项目的整个开发过程。Jenkins可以通过插件扩展其功能，支持各种编程语言和工具。它可以与版本控制系统（如Git、Subversion）、构建工具（如Apache Maven、Gradle）、测试框架（如JUnit、Selenium）以及部署工具（如Docker、Kubernetes）等集成。Jenkins的核心概念是作业（Job）。作业定义了构建过程的一系列步骤，包括代码的获取、编译、测试和部署等。通过配置作业，您可以指定何时触发构建、如何获取代码、构建步骤的顺序以及构建产物的处理方式。Jenkins还提供了一个可视化的用户界面，使用户可以方便地管理和监控作业、查看构建历史和日志，并设置触发条件和通知机制。它还支持分布式构建，可以在多台计算机上同时执行构建任务，以加快构建速度和提高效率。通过使用Jenkins，团队可以实现持续集成和持续交付的最佳实践，将软件的开发、测试和交付过程自动化，减少手动操作和人为错误，提高软件质量和交付速度。它广泛应用于各种软件开发项目和持续集成环境中。CI、CD安装JenkinsWindows安装Jenkins中文网：http://www.jenkins.org.cn/进群下载.msi文件进行安装Docker安装编写docker-compose.ymlversion: "3.1" services: jenkins: image: jenkins/jenkins:2.401.1-lts container_name: jenkins ports: - 8080:8080 volumes: - ./data/:/var/jenkins_home/ 2. 启动docker-compose docker-compose up -d ![image-20230621174121654](https://qny.chengxuyi.top//typora_img/image-20230621174121654.png) 这里看到启动失败了，查看容器日志发现是权限问题，无法进行write ![image-20230621174345882](https://qny.chengxuyi.top//typora_img/image-20230621174345882.png) 对data文件夹赋予777权限并启动再次容器 chmod -R 777 data docker start jenkins 3. 浏览器访问8080端口进入首页，密码可在容器日志中或者文件中查看 ![image-20230621175229386](https://qny.chengxuyi.top//typora_img/image-20230621175229386.png) 4. 安装插件，随便点击一个并等待插件安装完成 > 这里插件大概率会安装失败，不要紧，等下我们进去安装我们需要的插件，不用在这个地方纠结很久 ![image-20230621175504592](https://qny.chengxuyi.top//typora_img/image-20230621175504592.png) 5. 创建用户，这里随便输，记住账号密码即可 ![image-20230621175903669](https://qny.chengxuyi.top//typora_img/image-20230621175903669.png) 6. 实例配置使用默认值，点击保存并完成 ![image-20230621175954040](https://qny.chengxuyi.top//typora_img/image-20230621175954040.png) ## 安装插件 Jenkins的大部分功能都来自于它的插件，插件越多，功能越强大 进入插件页面 ![image-20230621180351804](https://qny.chengxuyi.top//typora_img/image-20230621180351804.png) 我们需要安装`Git Parameter`和`Publish Over SSH`2个插件 ![image-20230621180523507](https://qny.chengxuyi.top//typora_img/image-20230621180523507.png) 安装完并重启 ![image-20230621180544156](https://qny.chengxuyi.top//typora_img/image-20230621180544156.png) `Git Parameter`插件用于在连接Git仓库时添加额外的参数 `Publish Over SSH`插件用于连接远程服务器 ## Jenkins配置Maven、JDK、SSH 进入全局配置页面 ![image-20230625201915125](https://qny.chengxuyi.top//typora_img/image-20230625201915125.png) ### Maven 填写Name和Home路径 路径在填写错误时会有提示 ![image-20230625202056876](https://qny.chengxuyi.top//typora_img/image-20230625202056876.png) ### JDK ![image-20230625202237465](https://qny.chengxuyi.top//typora_img/image-20230625202237465.png) ### SSH ![image-20230625202325738](https://qny.chengxuyi.top//typora_img/image-20230625202325738.png) 滑到最底部找到 `Publish over SSH`并配置需要连接的服务器信息 ![image-20230625202855508](https://qny.chengxuyi.top//typora_img/image-20230625202855508.png) 使用密码进行验证 ![image-20230625202912132](https://qny.chengxuyi.top//typora_img/image-20230625202912132.png) ## CI CI（持续集成）是指在团队开发过程中，频繁地将代码集成到共享代码仓库中，并自动执行构建、测试和代码质量检查等过程。其目标是确保团队成员的代码能够及时合并，并尽早发现和解决集成问题。CI的关键是自动化构建和测试，以便尽早发现代码中的错误和问题。通过持续集成，团队可以更快地交付软件，减少集成问题的风险，并提高团队的协作效率。 > 本次案例使用项目为RuoYi前后端分离多模块项目：https://gitee.com/y_project/RuoYi-Vue > > 采用Docker容器的方式进行部署 1. 创建一个自定义风格的项目 ![image-20230625201202830](https://qny.chengxuyi.top//typora_img/image-20230625201202830.png) 2. 配置项目源码信息 ![image-20230625201700751](https://qny.chengxuyi.top//typora_img/image-20230625201700751.png) 测试代码是否拉取成功 ![image-20230625203259138](https://qny.chengxuyi.top//typora_img/image-20230625203259138.png) 查看控制台日志 ![image-20230625203325532](https://qny.chengxuyi.top//typora_img/image-20230625203325532.png) 拉取代码成功 ![image-20230625203346572](https://qny.chengxuyi.top//typora_img/image-20230625203346572.png) 拉取成功之后会在Jenkins的工作空间中看到项目文件夹 使用docker部署时在挂载的data/workspace文件夹中查看。 使用windows安装版本在图中的目录中查看 ![image-20230625203550793](https://qny.chengxuyi.top//typora_img/image-20230625203550793.png) 3. 添加项目构建步骤：调用顶层Maven目标 ![image-20230625203714474](https://qny.chengxuyi.top//typora_img/image-20230625203714474.png) ![image-20230625203927742](https://qny.chengxuyi.top//typora_img/image-20230625203927742.png) 再次进行构建并查看控制台日志 ![image-20230625204030927](https://qny.chengxuyi.top//typora_img/image-20230625204030927.png) 项目构建成功之后会在对应的工作空间的项目中生成target目录 4. 在项目根目录新建docker文件夹并编写Dockerfile和docker-compose文件 `/docker/Dockerfile` FROM daocloud.io/library/java:8u40-jdkCOPY ruoyi-admin.jar /usr/local/WORKDIR /usr/localCMD java -jar ruoyi-admin.jar `/docker/docker-compose.yml` version: "3.1" services: bms-project: build: context: ./ dockerfile: Dockerfile image: bms:v2.2 container_name: bms ports: - "4001:4001" **编写完代码记得提交到自己Git仓库** 5. 添加构建后操作：通过SSH发送构建工件 ![image-20230625205524397](https://qny.chengxuyi.top//typora_img/image-20230625205524397.png) ![image-20230626093529864](https://qny.chengxuyi.top//typora_img/image-20230626093529864.png) 6. 保存并执行任务 - 超时 ![image-20230626094020061](https://qny.chengxuyi.top//typora_img/image-20230626094020061.png) ![image-20230626094227457](https://qny.chengxuyi.top//typora_img/image-20230626094227457.png) 修改超时时间保存后再次执行 ![image-20230626094424578](https://qny.chengxuyi.top//typora_img/image-20230626094424578.png) 在目标服务器中使用`docker ps`查看已经部署成功 > **至此，CI操作就已经完成了** ## CD CD（持续交付/持续部署）是CI的延伸，指的是在通过持续集成构建、测试和验证代码后，自动将代码交付给生产环境或可用于生产部署的环境。持续交付的目标是使软件的交付过程自动化、可靠且可重复，以减少人工干预和减少交付的时间间隔。持续交付的流程通常包括自动化构建、自动化测试、自动化部署和自动化验证等步骤。持续部署则更进一步，指的是将经过验证的代码自动部署到生产环境中，以实现全自动的软件交付。 1. 在Gitee中配置标签 ![image-20230626095308436](https://qny.chengxuyi.top//typora_img/image-20230626095308436.png) 2. 在任务配置中选择参数化，并选择之前安装的`Git Parameter` ![image-20230626095442344](https://qny.chengxuyi.top//typora_img/image-20230626095442344.png) ![image-20230628164540903](https://qny.chengxuyi.top//typora_img/image-20230628164540903.png) 3. 新增一行构建之前的命令，切换到指定的tag分支。$tag取上面Git Parameter名称的值 ![image-20230628170215381](https://qny.chengxuyi.top//typora_img/image-20230628170215381.png) > windows环境中的Jenkins无法调用shell脚本问题 在系统配置里面中配置shell为Git的sh.exe执行文件路径 ![image-20230628170343041](https://qny.chengxuyi.top//typora_img/image-20230628170343041.png) 4. 在配置完参数后，构建按钮变成了Build with Parameters ![image-20230626095851626](https://qny.chengxuyi.top//typora_img/image-20230626095851626-16877447685341.png) 5. 选择对应的tag并开始构建 ![image-20230626095956108](https://qny.chengxuyi.top//typora_img/image-20230626095956108.png) 控制台查看执行了切换分支的命令 ![image-20230628170551950](https://qny.chengxuyi.top//typora_img/image-20230628170551950.png) ## SonarQube SonarQube（前身为Sonar）是一个开源的代码质量管理平台。它提供了一个集中的平台，用于对源代码进行静态代码分析、测量代码质量、跟踪技术债务、管理代码复杂性以及监控代码规范和安全性等方面的指标。SonarQube支持多种编程语言，包括Java、C/C++、C#、Python、JavaScript等，并提供了丰富的插件生态系统，以扩展和定制功能。SonarQube还提供了直观的仪表板和报告，用于可视化和监控代码质量的变化趋势。 ### Docker形式安装SonarQube 编写docker-compose.yml version: '3.1'services: db:image: postgres container_name: db ports: - 5432:5432 networks: - sonarnet environment: POSTGRES_USER: sonar POSTGRES_PASSWORD: sonarsonarqube:image: sonarqube:9.9-community container_name: sonarqube depends_on: - db ports: - 9000:9000 networks: - sonarnet environment: SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar SONAR_JDBC_USERNAME: sonar SONAR_JDBC_PASSWORD: sonarnetworks: sonarnet:driver: bridge 启动命令：docker-compose up -d **Windows启动失败查看SonarQube容器日志** bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] **启动失败解决办法：https://blog.csdn.net/qq_38680405/article/details/126700722** > 浏览器打开端口为9000 ### Maven与SonarQube集成 #### 修改Maven配置文件：settings.xml 在profiles标签中新增SonarQube配置信息并激活配置 <profile> <id>sonar</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <sonar.login>admin</sonar.login> <sonar.password>123456</sonar.password> <sonar.host.url>http://localhost:9000</sonar.host.url> </properties> </profile><activeProfile>sonar</activeProfile> #### 在项目根目录运行：mvn sonar:sonar ![image-20230625193319595](https://qny.chengxuyi.top//typora_img/image-20230625193319595.png) 在SonarQube提供的可视化界面查看检查结果 ![image-20230625193442430](https://qny.chengxuyi.top//typora_img/image-20230625193442430.png) ## SonarScanner SonarScanner是SonarQube的命令行工具，用于将源代码发送到SonarQube服务器进行分析。它是一个独立的客户端工具，可以与SonarQube进行集成，以便在分析阶段捕获和处理代码。SonarScanner通过读取配置文件（如`sonar-project.properties`）或通过命令行参数传递配置信息，确定需要分析的项目和相关设置。它会扫描项目的源代码，执行静态代码分析，并将结果提交到SonarQube服务器进行处理和展示。 SonarScanner支持多种构建工具和编程语言，包括Maven、Gradle、Ant、MSBuild等。它可以轻松地集成到持续集成（CI）和持续交付（CD）流程中，使开发团队能够在每次代码提交或构建时自动进行代码质量分析。 下载地址：https://docs.sonarqube.org/latest/analyzing-source-code/scanners/sonarscanner/ 下载自己对应的操作系统文件 ![image-20230625165342274](https://qny.chengxuyi.top//typora_img/image-20230625165342274.png) ### 命令行方式检查代码 #### 打开SonarScanner配置文件：sonar-scanner.properties ![image-20230625165522702](https://qny.chengxuyi.top//typora_img/image-20230625165522702.png) 更改后的文件内容为 Configure here general information about the environment, such as SonarQube server connection details for exampleNo information about specific project should appear here----- Default SonarQube server对应sonarQube的url地址sonar.host.url=http://localhost:9000----- Default source code encodingsonar.sourceEncoding=UTF-8 #### 执行检查 切换到SonarScanner目录cd E:environmentsonar-scanner-4.8.0.2856-windowsbin执行./sonar-scanner.bat -D sonar.java.binaries=.//target -D sonar.source=./ -D sonar.login=sqa_684223ae6877050107f0b3e3368e72fc06759874 -D sonar.projectKey=bms-project -D sonar.projectBaseDir=E:overload-workingbms-dianshang-project -D sonar.exclusions=RuoYi-Vue3/注释sonar.java.binaries 编译后的class文件位置sonar.source 源码位置sonar.login tokensonar.projectKey 项目的Keysonar.projectBaseDir 项目的基本路径sonar.exclusions 需要排除的文件夹或者文件 ## Jenkins集成SonarQubeScanner 在构建项目时对代码进行检查 1. Jenkins安装SonarQubeScanner插件 ![image-20230701093415322](https://qny.chengxuyi.top//typora_img/image-20230701093415322.png) 2. 生成密钥：打开SonarQube服务端 ![image-20230701094153984](https://qny.chengxuyi.top//typora_img/image-20230701094153984.png) 复制令牌 ![image-20230701094229335](https://qny.chengxuyi.top//typora_img/image-20230701094229335.png) 3. 配置SonarQube服务端 类型选择Secret text，输入复制的令牌 ![image-20230701094304636](https://qny.chengxuyi.top//typora_img/image-20230701094304636.png) ![image-20230701093949642](https://qny.chengxuyi.top//typora_img/image-20230701093949642.png) 4. 构建项目时添加SonarQubeScanner步骤 ![image-20230701094621711](https://qny.chengxuyi.top//typora_img/image-20230701094621711.png) ![image-20230701094814580](https://qny.chengxuyi.top//typora_img/image-20230701094814580.png) 5. 重新构建 > 在构建成功之后执行了SonarScanner命令进行检查 ![image-20230701095008286](https://qny.chengxuyi.top//typora_img/image-20230701095008286.png) SonarQube服务端也新增了一个检查 ![image-20230701095126527](https://qny.chengxuyi.top//typora_img/image-20230701095126527.png) ## Harbor Harbor是一个开源的企业级容器镜像仓库，用于存储、分发和管理Docker镜像。它提供了一个安全可靠的集中式存储库，使团队能够方便地共享和管理容器镜像。 下面是Harbor的一些主要特性： 1. **安全性和权限管理**：Harbor支持用户身份验证和授权机制，可以通过集成LDAP、Active Directory等进行用户认证。它还提供细粒度的访问控制，使管理员能够精确地管理用户对镜像的访问权限。 2. **镜像复制和同步**：Harbor支持镜像的复制和同步功能，可以在多个Harbor实例之间同步镜像。这有助于实现分布式部署和高可用性需求。 3. **漏洞扫描和安全审计**：Harbor集成了漏洞扫描工具，可以对上传到仓库中的镜像进行安全扫描，识别潜在的漏洞和安全风险。此外，Harbor还提供审计日志功能，记录了对仓库的操作和访问，方便进行安全审计。 4. **复制策略和镜像签名**：Harbor支持灵活的复制策略，可以定义哪些镜像需要复制到其他Harbor实例。此外，Harbor还支持镜像签名，以确保镜像的完整性和来源可信。 5. **项目和命名空间**：Harbor支持将镜像进行组织和管理，使用项目和命名空间来划分不同的逻辑单元。这有助于团队对镜像进行分类、管理和权限控制。 6. **可视化界面和API支持**：Harbor提供了易于使用的Web界面，使用户可以通过图形化界面进行镜像的上传、浏览和管理。此外，Harbor还暴露了一组RESTful API，方便与其他工具和系统进行集成。 总而言之，Harbor是一个功能丰富、安全可靠的容器镜像仓库，适用于企业级的容器镜像管理和分发需求。它提供了许多有用的特性，使团队能够轻松地构建、共享和管理容器镜像。 ### 安装Harbor [GitHub传送门](https://github.com/goharbor/harbor/releases)：选择离线或者在线版本 ![image-20230704194905334](https://qny.chengxuyi.top//typora_img/image-20230704194905334.png) 1. 将[harbor-offline-installer-v2.8.2.tgz](https://github.com/goharbor/harbor/releases/download/v2.8.2/harbor-offline-installer-v2.8.2.tgz)上传到服务器或虚拟机中并解压 2. 将`harbor.yml.tmpl`拷贝一份并重命名为`harbor.yml`。harbor启动时只会识别`harbor.yml`配置文件 3. 修改`harbor.yml`内容 ![image-20230704195702869](https://qny.chengxuyi.top//typora_img/image-20230704195702869.png) 4. 执行`install.sh`。harbor部署方式是使用docker容器部署，所有install之前需要先安装好Docker和Docker compose 5. 部署好查看Docker容器运行情况 ![image-20230704195931227](https://qny.chengxuyi.top//typora_img/image-20230704195931227.png) 6. 浏览器访问89端口 ![image-20230704200004857](https://qny.chengxuyi.top//typora_img/image-20230704200004857.png) ### Harbor基本操作 #### 新建项目 ![image-20230714163418205](https://qny.chengxuyi.top//typora_img/image-20230714163418205.png) ![image-20230714163428904](https://qny.chengxuyi.top//typora_img/image-20230714163428904.png) 输入项目名称、访问级别、项目配合限制：-1为不限制 ### 将镜像推送到Harbor 需要推送的目标服务器设置`daemon.json` `/etc/docker/daemon.json` { "registry-mirrors": [ "https://registry.hub.docker.com", "http://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn", "https://registry.docker-cn.com" ], "insecure-registries":["111.230.199.xxx:89"]} **重启docker** `systemctl restart docker` 1. 先给要推送的镜像打一个tag # 格式： docker tag 镜像ID HarborIP:端口/项目名/镜像名:版本号 docker tag 91b53e2624b4 111.230.199.xxx:89/test/mysql:v1.0.0 ![image-20230714164321072](https://qny.chengxuyi.top//typora_img/image-20230714164321072.png) 2. 登录到Harbor docker login 111.230.199.xxx:89 -u 用户名 -p 密码 ![image-20230714164353104](https://qny.chengxuyi.top//typora_img/image-20230714164353104.png) 3. 推送 docker push 111.230.199.xxx:89/test/mysql:v1.0.0 ![image-20230714164520134](https://qny.chengxuyi.top//typora_img/image-20230714164520134.png) 4. 推送完毕之后就可以在Harbor中看到 ![image-20230714164605854](https://qny.chengxuyi.top//typora_img/image-20230714164605854.png) ### 将镜像拉取到本地 Harbor进入到要拉取镜像的页面中复制拉取命令 ![image-20230714164642412](https://qny.chengxuyi.top//typora_img/image-20230714164642412.png) 复制后的命令docker pull 111.230.199.xxx:89/test/mysql@sha256:29ea1f451c3aad88df5a24288f76442286dc7fa6874d96a022e93a8a7efda880需要将后面的hash码替换成需要拉取的版本号docker pull 111.230.199.xxx:89/test/mysql:v1.0.0 ## Jenkins集成部署 当我们需要在多台服务器中同时部署项目时，如果按之前的方式从目标服务器中进行构建Docker镜像，就会造成在每一台服务器中都需要进行构建镜像的操作，为了避免这种情况。 我们可以在Jenkins中先将Docker镜像构建好，并推送到Harbor中，这样我们在目标服务器只需执行命令，将镜像从Harbor中拉取下来，并运行即可。这样就省去了重复构建的操作。 ### Jenkin制作自定义镜像并推送到Harbor 1. 创建一个自定义风格的任务 2. 设置Git源码地址 3. 调用顶层Maven目标进行打包 ![image-20230716210054716](https://qny.chengxuyi.top//typora_img/image-20230716210054716.png) package -Dmaven.test.skip=true 4. 在项目的Dockerfile路径执行构建镜像命令 ![image-20230717150433979](https://qny.chengxuyi.top//typora_img/image-20230717150433979.png) **问题：Jenkins无法直接执行的Docker命令（本案例Jenkins在WIndows环境中使用Docker进行部署）** ![image-20230716205949661](https://qny.chengxuyi.top//typora_img/image-20230716205949661.png) **解决：让Jenkins可以执行宿主机的Docker命令** 1. 修改Docker核心的sock文件所属组 路径：`/var/run/docker.sock` chown root:root docker.sock ``` 更改docker.sock的权限，使其对其他用户可读可写chmod o+rw docker.sock更改docker-compose.yml挂载信息，修改后：version: "3.1" services: jenkins: image: jenkins/jenkins:2.401.1-lts container_name: jenkins restart: always ports: - 8080:8080 volumes: - ./data/:/var/jenkins_home/ - /var/run/docker.sock:/var/run/docker.sock - /usr/bin/docker:/usr/bin/docker - /etc/docker/daemon.json:/etc/docker/daemon.json environment: - TZ=Asia/Shanghai ``` 进入Jenkins容器内部使用docker命令进行测试成功再次进行构建发现已经执行了Docker构建命令的操作文件不存在在构建之前需要将jar包移动到docker文件夹中mv ruoyi-admin/target/*.jar docker/ docker build -t ${JOB_NAME}:$tag docker/构建成功，查看宿主机镜像登录到Harbor，将镜像打一个tag并推送到Harbormv ruoyi-admin/target/*.jar docker/ docker build -t ${JOB_NAME}:$tag docker/ docker login -u admin -p Harbor1xxxx 111.230.199.xxx:89 docker tag ${JOB_NAME}:$tag 111.230.199.xxx:89/test/${JOB_NAME}:$tag docker push 111.230.199.xxx:89/test/${JOB_NAME}:$tag docker image prune -f查看宿主机镜像和Harbor是否推送成功到此推送流程就已经结束了目标服务器准备脚本文件脚本文件需要放置/usr/bin路径下，确保在服务器的哪个地方都可以运行此脚本文件harbor_addr=$1 harbor_repo=$2 project=$3 version=$4 container_port=$5 host_port=$6 imageName=$harbor_addr/$harbor_repo/$project:$version echo $imageName containerId=`docker ps -a | grep ${project} | awk '{print $1}'` echo $containerId if [ "$containerId" != "" ] ; then docker stop $containerId docker rm $containerId fi tag=`docker images | grep ${project} | awk '{print $2}'` echo $tag if "$tag" =~ "$version" ; then docker rmi $imageName fi docker pull $imageName docker run -d -p $host_port:$container_port --name $project $imageName echo "SUCCESS" 完成基于Harbor的最终部署添加2个字符串参数（容器内部端口、宿主机端口）Send build artifacts over SSH如果需要同时在多台服务器上部署，只需添加多个Send build artifacts over SSH即可。前提是每台服务器都安装好了Docker执行脚本文件deploy.sh 111.230.199.xxx:89 test ${JOB_NAME} $tag $container_port $host_port构建运行Jenkins流水线任务初体验