3.從0實(shí)現(xiàn)Online Judge(go語(yǔ)言)-Docker相關(guān)

源碼見(jiàn):https://github.com/lovercode/GO_OJ.git灵妨,demo見(jiàn):https://codelover.me/run.html

Docker相關(guān)

compilerrunner都是運(yùn)行在docker容器中湾宙,可以進(jìn)行資源限制和隔離,主要的實(shí)現(xiàn)如下。

初始化compiler容器

主要是根據(jù)配置文件來(lái)啟動(dòng)多個(gè)compiler的容器

func init() {
    for num := uint64(0); num < conf.GlobalConfig.CompilerNum; num++ {
        go initCompilerDocker(conf.GlobalConfig.CompilerDocker)
    }

}

func initCompilerDocker(Conf conf.DockerConfig) {
    ctx := context.Background()
    cli, err := client.NewClientWithOpts(client.WithVersion("1.18"))
    if err != nil {
        panic(err)
    }

    if err != nil {
        panic(err)
    }
    Config := container.Config{
        Image:      Conf.DockerName,
        Cmd:        Conf.Cmd,
        WorkingDir: Conf.WorkDir,
    }
    var mounts []mount.Mount
    for k, v := range Conf.DockerMount {
        mounts = append(mounts, mount.Mount{
            Type:   mount.TypeBind,
            Source: k,
            Target: v,
        })
    }

    HostConfig := container.HostConfig{
        Mounts: mounts,
        // Resources:      Resources,
        ReadonlyRootfs: Conf.ReadonlyRootfs,
        // Runtime:        "runsc",
    }
    if Conf.Memory >= 4194304 { //<4m設(shè)置無(wú)效
        Resources := container.Resources{
            Memory:    Conf.Memory,   //4m
            CPUQuota:  Conf.CpuQuota, //CPU資源的絕對(duì)限制,一般和CpuPeriod結(jié)合在一起,CpuQuota/CpuPeriod壶栋,就是能夠使用的核數(shù)
            CPUPeriod: Conf.CpuPeriod,
        }
        HostConfig.Resources = Resources
    }
    resp, err := cli.ContainerCreate(ctx, &Config, &HostConfig, nil, "")
    defer cli.ContainerRemove(ctx, resp.ID, types.ContainerRemoveOptions{Force: true})

    if err != nil {
        panic(err)
    }

tag:
    if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
        panic(err)
    }

    var res container.ContainerWaitOKBody
    statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)

    select {
    case err := <-errCh:
        if err != nil {
            log.Println("編譯機(jī)出錯(cuò)退出")
            goto end
        }
    case res = <-statusCh:
        if res.StatusCode != 0 {

        }

        log.Println("編譯機(jī)退出,準(zhǔn)備重啟...")
        goto tag
    }
end:
    log.Println("編譯機(jī)退出...")

}

  • 配置文件
CompilerNum=1
CompileDataPath="/home/codelover/go/src/go_oj/bin/run"
[CompilerDocker]
    Memory=-1
    CpuQuota=100000
    CpuPeriod=100000
    DockerName = "compiler:v2"
    Cmd = ["/bin/sh", "-c", "./compiler"]
    WorkDir = "/compiler"
    [CompilerDocker.DockerMount]
        "/home/codelover/go/src/go_oj/bin" = "/compiler"

初始化所有runner容器

與初始化compiler一樣普监,讀取配置直接初始化


func init() {
    for _, v := range conf.GlobalConfig.RunnerDocker {
        for num := 0; num < v.RunNum; num++ {
            go initRunnerDocker(v)
        }
    }
}

func initRunnerDocker(Conf conf.DockerConfig) {
    ctx := context.Background()
    cli, err := client.NewClientWithOpts(client.WithVersion("1.37"))
    if err != nil {
        panic(err)
    }

    if err != nil {
        panic(err)
    }
    Config := container.Config{
        Image:      Conf.DockerName,
        Cmd:        Conf.Cmd,
        WorkingDir: Conf.WorkDir,
    }
    var mounts []mount.Mount
    for k, v := range Conf.DockerMount {
        mounts = append(mounts, mount.Mount{
            Type:   mount.TypeBind,
            Source: k,
            Target: v,
            // ReadOnly: true,
        })
    }
    Init := true
    HostConfig := container.HostConfig{
        Mounts:         mounts,
        ReadonlyRootfs: Conf.ReadonlyRootfs,
        Init:           &Init,
        // Runtime:        "runsc",
    }
    if Conf.Memory >= 4194304 { //<4m設(shè)置無(wú)效
        Resources := container.Resources{
            Memory:    Conf.Memory,   //4m
            CPUQuota:  Conf.CpuQuota, //CPU資源的絕對(duì)限制贵试,一般和CpuPeriod結(jié)合在一起,CpuQuota/CpuPeriod凯正,就是能夠使用的核數(shù)
            CPUPeriod: Conf.CpuPeriod,
        }
        HostConfig.Resources = Resources
    }
    resp, err := cli.ContainerCreate(ctx, &Config, &HostConfig, nil, "")
    defer cli.ContainerRemove(ctx, resp.ID, types.ContainerRemoveOptions{Force: true})

    if err != nil {
        panic(err)
    }

tag:
    if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
        panic(err)
    }

    var res container.ContainerWaitOKBody
    statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)

    select {
    case err := <-errCh:
        if err != nil {
            log.Println("運(yùn)行機(jī)出錯(cuò)退出", err)
            goto end
        }
    case res = <-statusCh:
        if res.StatusCode != 0 {

        }

        log.Println("運(yùn)行機(jī)退出锡移,準(zhǔn)備重啟...", res)
        goto tag
    }
end:
    log.Println("運(yùn)行機(jī)退出...")


}
  • 配置如下
#c語(yǔ)言
[RunnerDocker.1]
    RunNum=1
    Memory=419430400
    CpuQuota=50000
    CpuPeriod=100000
    ReadonlyRootfs=false
    DockerName="alpine_c:latest"
    Cmd = ["./runner","conf/runner_config_1.toml"]
    WorkDir = "/runner"
    [RunnerDocker.1.DockerMount]
        "/home/codelover/go/src/go_oj/bin" = "/runner"

#php
[RunnerDocker.5]
    RunNum=1
    Memory=-1
    CpuQuota=100000
    CpuPeriod=100000
    ReadonlyRootfs=false
    DockerName="alpine_php:latest"
    Cmd = ["./runner","conf/runner_config_5.toml"]
    WorkDir = "/runner"
    [RunnerDocker.5.DockerMount]
        "/home/codelover/go/src/go_oj/bin" = "/runner"
        

dockerfile

  • 編譯機(jī)需要有所有編譯環(huán)境
FROM frolvlad/alpine-glibc:latest
RUN apk add --no-cache gcc &&\
    apk add --no-cache g++ &&\
    apk add --no-cache php &&\
    apk add --no-cache openjdk8 &&\
    apk add --no-cache pyflakes &&\
    apk add --no-cache go &&\
    apk add --no-cache libstdc++ 
ENV PATH "$PATH:/usr/lib/jvm/default-jvm/bin"
    

  • 運(yùn)行機(jī)dockerfile示例(php)
    user用于運(yùn)行用戶(hù)程序
FROM frolvlad/alpine-glibc:latest
RUN adduser -D user0 -G nogroup &&\
    adduser -D user1 -G nogroup &&\
    adduser -D user2 -G nogroup &&\
    adduser -D user3 -G nogroup &&\
    adduser -D user4 -G nogroup &&\
    adduser -D user5 -G nogroup &&\
    adduser -D user6 -G nogroup &&\
    adduser -D user7 -G nogroup &&\
    adduser -D user8 -G nogroup &&\
    adduser -D user9 -G nogroup &&\
    adduser -D user10 -G nogroup &&\
    apk add --no-cache php7 &&\
    apk add --no-cache libseccomp-dev
    

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市漆际,隨后出現(xiàn)的幾起案子淆珊,更是在濱河造成了極大的恐慌,老刑警劉巖奸汇,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件施符,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡擂找,警方通過(guò)查閱死者的電腦和手機(jī)戳吝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)贯涎,“玉大人听哭,你說(shuō)我怎么就攤上這事√瘤ǎ” “怎么了陆盘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)败明。 經(jīng)常有香客問(wèn)我隘马,道長(zhǎng),這世上最難降的妖魔是什么妻顶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任酸员,我火速辦了婚禮蜒车,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘幔嗦。我一直安慰自己酿愧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布邀泉。 她就那樣靜靜地躺著寓娩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呼渣。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天寞埠,我揣著相機(jī)與錄音屁置,去河邊找鬼。 笑死仁连,一個(gè)胖子當(dāng)著我的面吹牛蓝角,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饭冬,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼使鹅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了昌抠?” 一聲冷哼從身側(cè)響起患朱,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炊苫,沒(méi)想到半個(gè)月后裁厅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侨艾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年执虹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唠梨。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袋励,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出当叭,到底是詐尸還是另有隱情茬故,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布蚁鳖,位于F島的核電站均牢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏才睹。R本人自食惡果不足惜徘跪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一甘邀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧垮庐,春花似錦松邪、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至寒亥,卻和暖如春邮府,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背溉奕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工褂傀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人加勤。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓仙辟,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鳄梅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叠国,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容