知乎专栏 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.3</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <sonar.projectKey>netkiller.cn_java_AX0HsoVkT19KeT2iVgUT</sonar.projectKey> <sonar.qualitygate.wait>true</sonar.qualitygate.wait> <docker.registry>registry.netkiller.cn/netkiller.cn</docker.registry> </properties> <repositories> <repository> <id>gitlab-maven</id> <url>${env.CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url> </repository> </repositories> <distributionManagement> <repository> <id>gitlab-maven</id> <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url> </repository> <snapshotRepository> <id>gitlab-maven</id> <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url> </snapshotRepository> </distributionManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <!-- <version>4.13.2</version> --> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>1.2.2</version> <configuration> <imageName>${docker.registry}/${project.artifactId}</imageName> <baseImage>openjdk:8-alpine</baseImage> <maintainer>netkiller@msn.com</maintainer> <volumes>/srv</volumes> <workdir>/srv</workdir> <env> <JAVA_OPTS>-server -Xms512m -Xmx4096m -Djava.security.egd=file:/dev/./urandom</JAVA_OPTS> </env> <exposes>8080</exposes> <entryPoint>["sh", "-c", "/srv/docker-entrypoint.sh"]</entryPoint> <resources> <resource> <targetPath>/srv</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> <resource> <targetPath>/srv</targetPath> <directory>.</directory> <include>docker-entrypoint.sh</include> </resource> </resources> <registryUrl>http://${docker.registry}/v2/</registryUrl> <imageTags> <imageTag>${project.version}</imageTag> <imageTag>latest</imageTag> </imageTags> </configuration> </plugin> </plugins> </build> </project>
在项目目录创建 docker-entrypoint.sh 文件
#!/bin/sh if [ ! -z $1 ]; then MODULE=$1 shift fi if [ -z $JAVA_OPTS ]; then JAVA_OPTS='-Xms1024m -Xmx4096m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT+8 -Dfile.encoding=utf-8' fi if [ -z $MODULE ]; then echo "MODULE environment is not set" exit 127 else PACKAGE=/srv/$MODULE.jar fi DEBUG='-Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=5555' SKYWALKING="-javaagent:/srv/skywalking/agent/skywalking-agent.jar -Dskywalking.collector.backend_service=oap.netkiller.cn:11800 -Dskywalking.agent.service_name=${MODULE}" exec java ${JAVA_OPTS} -jar ${PACKAGE} $@
暂时 DEBUG,SKYWALKING 没有使用,放在一遍不碍事。脚本的用法
./docker-entrypoint.sh your_module --server.port=8080
运行 mvn 命令构建 docker 镜像
neo@Netkiller-iMac ~/w/java.netkiller.cn (master)> mvn package docker:build docker:push
不出预料,你会看到下面输出
[INFO] Building image registry.netkiller.cn/netkiller.cn/demo Step 1/9 : FROM openjdk:8-alpine ---> a3562aa0b991 Step 2/9 : MAINTAINER netkiller@msn.com ---> Using cache ---> b4a79be602ae Step 3/9 : ENV JAVA_OPTS -server -Xms512m -Xmx4096m -Djava.security.egd=file:/dev/./urandom ---> Using cache ---> 9d685ea4a0d3 Step 4/9 : WORKDIR /srv ---> Using cache ---> e2feea451bb1 Step 5/9 : ADD /srv/demo-0.0.1-SNAPSHOT.jar /srv/ ---> 7ad53fb991b8 Step 6/9 : ADD /srv/docker-entrypoint.sh /srv/ ---> 39def6507064 Step 7/9 : EXPOSE 8080 ---> Running in 338a99e6ec36 Removing intermediate container 338a99e6ec36 ---> f192b73ab3b9 Step 8/9 : ENTRYPOINT ["sh", "-c", "/srv/docker-entrypoint.sh"] ---> Running in 5bda82acd305 Removing intermediate container 5bda82acd305 ---> 85c1b2615a97 Step 9/9 : VOLUME /srv ---> Running in 27d71c55bf7e Removing intermediate container 27d71c55bf7e ---> 64e0d8992fdd ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null} Successfully built 64e0d8992fdd Successfully tagged registry.netkiller.cn/netkiller.cn/demo:latest [INFO] Built registry.netkiller.cn/netkiller.cn/demo [INFO] Tagging registry.netkiller.cn/netkiller.cn/demo with 0.0.1-SNAPSHOT [INFO] Tagging registry.netkiller.cn/netkiller.cn/demo with latest
查看镜像
neo@Netkiller-iMac ~/w/java.netkiller.cn (master)> docker image ls | grep netkiller registry.netkiller.cn/netkiller.cn/demo 0.0.1-SNAPSHOT 64e0d8992fdd 3 minutes ago 122MB registry.netkiller.cn/netkiller.cn/demo latest 64e0d8992fdd 3 minutes ago 122MB
from netkiller.kubernetes import * namespace = 'default' compose = Compose('development') module = 'demo' # version = '0.0.1-SNAPSHOT' version = 'latest' deployment = Deployment() deployment.apiVersion('apps/v1') deployment.metadata().name(module).labels({'app': module}).namespace(namespace) deployment.spec().replicas(1) deployment.spec().selector({'matchLabels': {'app': module}}) deployment.spec().template().metadata().labels({'app': module}) deployment.spec().template().spec().containers().name(module).image( 'registry.netkiller.cn/netkiller.cn/cloud.netkiller.cn:%s' % version).ports([{ 'containerPort': 8080 }]).env([ {'name': 'TZ', 'value': 'Asia/Shanghai'}, {'name': 'LANG', 'value': 'en_US.UTF-8'}, ]).args([module,'--server.port=8080']) # deployment.debug() # deployment.json() service = Service() service.metadata().name(module) service.metadata().namespace(namespace) service.spec().selector({'app': module}) service.spec().type('NodePort') service.spec().ports([{ 'name': 'http', 'protocol': 'TCP', 'port': 8080, 'targetPort': 8080 }]) compose.add(deployment) compose.add(service) print("=" * 40, "Compose", "=" * 40) compose.debug() compose.delete() compose.create()⏎
查看容器运行状态
neo@Netkiller-iMac ~/w/java.netkiller.cn (master)> kubectl get pods NAME READY STATUS RESTARTS AGE nginx-88c84c4d8-8pmzp 1/1 Running 1 3d20h demo-76b7598b76-5hstp 1/1 Running 0 5h43m busybox 0/1 CrashLoopBackOff 52 4h44m
容器中不方便修改配置文件,我们可以使用环境变量覆盖配置
JAVA_OPTS=-Dspring.cloud.nacos.username=nacos \ -Dspring.cloud.nacos.password=nacos \ -Dspring.cloud.nacos.config.server-addr=mse-032dbef0-nacos-ans.mse.aliyuncs.com:8848 \ -Dspring.cloud.nacos.discovery.server-addr=mse-032dbef0-nacos-ans.mse.aliyuncs.com:8848 \
相当于
java -Dspring.cloud.nacos.username=nacos \ -Dspring.cloud.nacos.password=nacos \ -Dspring.cloud.nacos.config.server-addr=mse-032dbef0-nacos-ans.mse.aliyuncs.com:8848 \ -Dspring.cloud.nacos.discovery.server-addr=mse-032dbef0-nacos-ans.mse.aliyuncs.com:8848 \ -jar netkiller.jar