docker~Dockerfile方式生成控制臺和Api項目(mu)的(de)鏡像(xiang)
一些理論知識
將控制臺程序和API程序部署到docker,然后運行它,這(zhe)個首先要解決的問題(ti)就是(shi)如何在linux平臺運行(xing)C#代碼,哈(ha)哈(ha),很古(gu)老(lao)的問(wen)題(ti),事(shi)實上(shang),對(dui)于(yu)這種問(wen)題(ti)早在幾(ji)年前就已經有了解決方案,那就是(shi)在linux上(shang)安裝mono開(kai)發環境,然后使用mono就可(ke)以(yi)運行C#代碼(ma)了,而(er)如果你(ni)的C#是(shi)一(yi)個網站(zhan)形式的,那需(xu)要一(yi)個宿主的支持,其中最權威的應該就是(shi)jexus框架(jia),你(ni)可(ke)以(yi)把當(dang)理解成是(shi)一(yi)個服務器,就像(xiang)tomcat,iis這種東西。
上一次中我們使用mono原始鏡像生成了一個新的鏡像,用來輸出hello world,事實(shi)上(shang),我的(de)(de)本意(yi)不在(zai)echo一個(ge)字符出來,而是為(wei)今天(tian)(tian)的(de)(de)課(ke)打下基(ji)礎,因為(wei)今天(tian)(tian)就(jiu)真的(de)(de)要在(zai)linux上(shang)運行(xing)C#了(le),或(huo)者(zhe)說(shuo)把C#項(xiang)目部署(shu)到docker上(shang)了(le)。
說干就干-控制臺程序
首先要求你的控制(zhi)臺(tai)程序(xu)與你的Dockerfile在同(tong)級目(mu)錄,如果是(shi)publish之后的代碼(ma),那最(zui)好也(ye)放(fang)在同(tong)一(yi)目(mu)錄下,這樣方便你Dockerfile的部署
# 使(shi)用(yong)一個基礎的鏡像
FROM mono
# 將文件復制到docker容器
COPY hello.exe .
# 使用mono運行一個應用程序
CMD mono hello.exe
上(shang)面代(dai)碼的工(gong)作流程:
- 要使用一個基礎鏡像mono,如果本地沒有會去下載它,如果有直接使用本地鏡像
- 將Dockerfile同級目錄下的hello.exe文件復制到docker里,只有這里,你的docker里的程序才找的到它
- 運行一個mono命令,如果你的mono沒有環境變量(profile),你需要使用WORKDIR去指定目錄)

說干就干-API程序
api程(cheng)序比(bi)控制臺就復雜(za)一(yi)些(xie),你可(ke)(ke)以使用(yong)jexus作為宿(su)主,也可(ke)(ke)以使用(yong)api自己SelfHost,我們今天主要(yao)說(shuo)說(shuo)后者,它比(bi)較輕量級,事實上它也是一(yi)個控制臺程(cheng)序,只不(bu)過安裝了一(yi)些(xie)包包,來提供(gong)宿(su)主功能。
<?xml version="1.0" encoding="utf-8"?> <packages> <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" /> <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" /> <package id="Microsoft.AspNet.WebApi.SelfHost" version="5.2.3" targetFramework="net452" /> <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" /> </packages>
然后在(zai)代碼(ma)里去(qu)建(jian)(jian)立路(lu)由,監(jian)聽端口,建(jian)(jian)立控(kong)制(zhi)器等(deng)
static void Main(string[] args) { var config = new HttpSelfHostConfiguration("//localhost:5000"); //配置主機(ji) config.Routes.MapHttpRoute( "Default", "api/{controller}/{id}", new { id = RouteParameter.Optional }); //數(shu)據(ju)返回格式 config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); using (HttpSelfHostServer server = new HttpSelfHostServer(config)) //監聽HTTP { server.OpenAsync().Wait(); //開啟來自客戶端(duan)的請(qing)求(qiu) Console.WriteLine("Listen 5000 port,Press Enter to quit."); Console.ReadKey(); } }
這(zhe)時,我們生成項目后(hou),就(jiu)可(ke)以(yi)為它編譯自己的Dockerfile了,然后(hou)通過(guo)docker build就(jiu)可(ke)以(yi)建立自己的鏡(jing)像了,通過(guo)docker run就(jiu)可(ke)以(yi)把服務運行(xing)起來了。
#使用一個基礎(chu)的鏡像 FROM mono #開放端口 EXPOSE 8080 #將Release目(mu)錄下的所(suo)有文件復制到docker容器(qi)的根目(mu)錄,注(zhu)意不(bu)會建立(li)Release目(mu)錄 COPY Release/ . #使用mono運行一個應用程序(xu) #CMD mono selfWeb.exe
我們生成這個鏡像之前,然后去運行它,我們使用交互模式去運行,然后進入容器后,我們手動去執行mono selfWeb.exe ,當(dang)然(ran)也可以做(zuo)成自己執(zhi)行的!
docker run -it imageID

當進入容器(qi)后(hou),我們就(jiu)可以執行(xing)自己(ji)的命令了(le),這時你(ni)可以ls一個看看根目(mu)錄的情況,事實上我們API的Release下所有(you)文(wen)件都(dou)被復制過(guo)來了(le)。

mono selfWeb.exe

這時,mono幫(bang)我們運行了這個api的宿主程序(xu),它對外界會開放一個8080端口!
小伙(huo)伴(ban)可以(yi)訪問:Http://dockerip:8080,來感受一下了!