Ctrl K
ComunidadGuías…

builder/build/netcore_build.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// RAINBOND, Application Management Platform
// Copyright (C) 2014-2017 Goodrain Co., Ltd.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. For any non-GPL usage of Rainbond,
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
// must be obtained first.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package build

import (
	"fmt"
	"github.com/goodrain/rainbond/builder/parser/code"
	"github.com/goodrain/rainbond/db"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/goodrain/rainbond/builder/sources"
	"github.com/goodrain/rainbond/event"
	"github.com/goodrain/rainbond/util"
	"github.com/sirupsen/logrus"
)

var netDockerfileTmpl = `
FROM ${DOTNET_SDK} AS builder
WORKDIR /app

# copy csproj and restore as distinct layers
COPY . .
RUN ${DOTNET_RESTORE_PRE} && ${DOTNET_RESTORE:dotnet restore} && dotnet publish -c Release -o /out

FROM ${DOTNET_RUNTIME}
WORKDIR /app
COPY --from=builder /out/ .
CMD ["dotnet"]
`

var nodeJSStaticDockerfileTmpl = `
FROM node:${RUNTIMES:20}-bullseye-slim AS builder
COPY . /app
WORKDIR /app
RUN ${PACKAGE_TOOL:npm} config set registry ${NPM_REGISTRY:https://registry.npmmirror.com} && ${PACKAGE_TOOL:npm} install && ${NODE_BUILD_CMD:npm run build}

FROM nginx:alpine
COPY nginx.k8s.conf /etc/nginx/conf.d/default.conf

COPY --from=builder /app/${DIST_DIR:dist} /opt/${DIST_DIR:dist}
`

var nginxTemplate = `
server {
    listen       5000;
    
    location / {
        root /opt/${DIST_DIR:dist};
    }
}
`

type customDockerfileBuild struct {
	imageName      string
	buildImageName string
	sourceDir      string
	logger         event.Logger
	serviceID      string
	imageClient    sources.ImageClient
}

func customDockerBuilder() (Build, error) {
	return &customDockerfileBuild{}, nil
}

func (d *customDockerfileBuild) Build(re *Request) (*Response, error) {
	defer d.clear()
	d.logger = re.Logger
	d.serviceID = re.ServiceID
	d.sourceDir = re.SourceDir
	d.imageName = CreateImageName(re.ServiceID, re.DeployVersion)
	d.imageClient = re.ImageClient

	re.Logger.Info("start compiling the source code", map[string]string{"step": "builder-exector"})
	// write dockerfile
	if err := d.writeDockerfile(d.sourceDir, re.BuildEnvs, re.Lang); err != nil {
		return nil, fmt.Errorf("write default dockerfile error:%s", err.Error())
	}
	// build image
	err := sources.ImageBuild(re.Arch, d.sourceDir, re.RbdNamespace, re.ServiceID, re.DeployVersion, re.Logger, "nc-build", "", re.BuildKitImage, re.BuildKitArgs, re.BuildKitCache, re.KubeClient)
	if err != nil {
		re.Logger.Error(fmt.Sprintf("build image %s failure, find log in rbd-chaos", d.buildImageName), map[string]string{"step": "builder-exector", "status": "failure"})
		logrus.Errorf("build image error: %s", err.Error())
		return nil, err
	}
	re.Logger.Info("push image to push local image registry success", map[string]string{"step": "builder-exector"})
	if err := d.imageClient.ImageRemove(d.imageName); err != nil {
		logrus.Errorf("remove image %s failure %s", d.imageName, err.Error())
	}
	return d.createResponse(), nil
}

func (d *customDockerfileBuild) writeDockerfile(sourceDir string, envs map[string]string, lang code.Lang) error {
	if lang == code.NetCore {
		version := envs["DOTNET_SDK_VERSION"]
		compilerVersion, err := db.GetManager().LongVersionDao().GetVersionByLanguageAndVersion("net_sdk", version)
		if err != nil {
			return err
		}
		version = envs["DOTNET_RUNTIME_VERSION"]
		runtimeVersion, err := db.GetManager().LongVersionDao().GetVersionByLanguageAndVersion("net_runtime", version)
		if err != nil {
			return err
		}
		envs["DOTNET_SDK"] = compilerVersion.FileName
		envs["DOTNET_RUNTIME"] = runtimeVersion.FileName
	}
	dockerfile := util.ParseVariable(netDockerfileTmpl, envs)
	// Handle Node.js projects with DOCKERFILE mode
	// Check for Node.js language (including combined types like "Node.js,static")
	if strings.Contains(string(lang), "Node") && envs["MODE"] == "DOCKERFILE" {
		if envs["NODE_BUILD_CMD"] == "" {
			envs["NODE_BUILD_CMD"] = envs["PACKAGE_TOOL"] + " run build"
		}
		dockerfile = util.ParseVariable(nodeJSStaticDockerfileTmpl, envs)
		dPath := path.Join(sourceDir, "nginx.k8s.conf")
		nginxFile := util.ParseVariable(nginxTemplate, envs)
		err := ioutil.WriteFile(dPath, []byte(nginxFile), 0755)
		if err != nil {
			return err
		}
	}
	dfpath := path.Join(sourceDir, "Dockerfile")
	logrus.Debugf("dest: %s; write dockerfile: %s", dfpath, dockerfile)
	return ioutil.WriteFile(dfpath, []byte(dockerfile), 0755)
}

func (d *customDockerfileBuild) createResponse() *Response {
	return &Response{
		MediumType: ImageMediumType,
		MediumPath: d.imageName,
	}
}

func (d *customDockerfileBuild) clear() {
	os.Remove(path.Join(d.sourceDir, "Dockerfile"))
}