1. 程式人生 > >ASP.Net Core2.1 秒殺專案一步一步實現CI/CD系列一

ASP.Net Core2.1 秒殺專案一步一步實現CI/CD系列一

前言:有一段時間沒寫部落格了,那是因為博主菜,需要學習和準備,這不帶來了本系列的文章。在這裡我把學習的心得分享出來,有些點理解的也不是太到位,希望大佬們能多多給點建議和指導。下半年就把這個系列的文章寫完,使用的技術暫時先不說,保持神祕感。哈哈哈

 

一、專案介紹

該專案整體上使用的是ASP.Net Core2.1,沒有按照DDD來分層,因為博主不會,O(∩_∩)O哈哈~,專案中使用的分層具體參考的是張輝清老師的《中小研發團隊架構實踐》,專案整體整體分層如下圖所示:

 目前為了簡單,專案沒有按照DDD來分層,先把第一版的寫完,後面有時間的話再使用DDD來重構。原始碼暫時先不公開,都是一些很簡單的東西,寫這系列的文章初衷是讓大家熟悉微服務的整個流程。

二、Docker安裝

 關於Docker的基礎知識,在這裡不會講解,可以通過其他途徑學習,在這裡,我只簡單介紹一下在Centos7.3上安裝Docker(跟著官方文件也可以:https://docs.docker.com/install/linux/docker-ce/centos/)

(1)如果之前你裝過,沒有解除安裝乾淨,請執行下面的操作

$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

 

 (2)安裝倉儲

$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

 

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

 

(3)安裝Docker

$ sudo yum install docker-ce docker-ce-cli containerd.io

 

(4)啟動Docker服務

$ sudo systemctl start docker

 

(5)檢視Docker版本

[root@localhost ~]# docker version

 

看到這樣的結果說明Docker是安裝成功了

 

三、Docker的基本命令

part 1、熱身命令

 (1)檢視映象:docker image ls

(2)檢視容器:docker container ls

注意:

  •  使用docker  container ls 檢視當前本地正在執行的容器, 前面使用docker run image的名字  可以執行該容器,但是執行完就會結束,並不是一個常駐記憶體的程序

(3)檢視容器:docker container ls -a

注意:

  • docker container ls -a  會列出所有的容器包括正在執行的也包括退出的。當我們通過docker run 去基於一個image建立一個容器的時候,預設回去執行cmd的命令。

細心的同學會發現,如果本地沒有對應的映象,會自動到遠端倉儲中拉取,地址:https://hub.docker.com/,當我們再使用docker container ls -a,會發現多了一個容器。

 

(4)後臺啟動容器:docker run -it centos

 注意:

  • 一定要注意那些操作是在容器當中,那些是在宿主機中。

我們也可以在容器中進行讀寫檔案:

 

(5)退出容器

ctrl+d可以直接退出容器

 

注意:

  • 單純的想在容器中儲存資訊,是有問題的,因為容器是不能持久化資料的,想儲存資料涉及到其他方面的知識,這裡就暫時不展開了。

 

part2、docker命令

有關docker的命令分為兩大類:管理命令和命令

管理命令是對docker內的物件進行管理,這裡我只說說一下幾個,關於更多的命令,可以參考文件。

(1)刪除具體某個容器 :docker container rm  xxxxx      這裡的xxxxx  指的是CONTAINER ID

(2)刪除具體的image:docker image rm  xxxxx      xxxxx      指的是映象ID

 注意刪除image時,先把容器停掉,在刪除容器,最後再刪除image。好了關於docker的命令就講到這裡。讓我們嘗試著構建自己的專案映象。

四、Docker中部署專案

 (1)在部署前,先在專案中建立Dockerfile

FROM microsoft/dotnet:2.1-aspnetcore-runtime
LABEL maintainer="[email protected]"
RUN mkdir /data
COPY ./ /data
WORKDIR /data
EXPOSE 80
CMD [ "dotnet","Spike.Api.dll" ]

(2)然後點擊發布,把釋出後的內容上傳到虛擬機器中 /data/publish資料夾下,具體內容如下:

 注意:不要忘記Dockerfile檔案了。

(3)接下來,構建自己的映象

[root@localhost publish]# docker build -f ./Dockerfile -t guozheng007/spike:v2 .
Sending build context to Docker daemon 16.23MB
Step 1/7 : FROM microsoft/dotnet:2.1-aspnetcore-runtime
---> 81472b549eb2
Step 2/7 : LABEL maintainer="[email protected]"
---> Using cache
---> 18deb5693198
Step 3/7 : RUN mkdir /data
---> Using cache
---> 47b4b4e77f1a
Step 4/7 : COPY ./ /data
---> 10f80a57a6c1
Step 5/7 : WORKDIR /data
---> Running in 45867fc7ec79
Removing intermediate container 45867fc7ec79
---> 39bd97e0b669
Step 6/7 : EXPOSE 80
---> Running in 92d8c475a18f
Removing intermediate container 92d8c475a18f
---> d7753067afa7
Step 7/7 : CMD [ "dotnet","Spike.Api.dll" ]
---> Running in 5b94f4ff3c44
Removing intermediate container 5b94f4ff3c44
---> c15413ef3f96
Successfully built c15413ef3f96
Successfully tagged guozheng007/spike:v2

 (4)啟動容器

 下面我們就使用上面的命令,來看看image是夠構建成功

[root@localhost publish]# docker images
REPOSITORY                   TAG                      IMAGE ID            CREATED              SIZE
guozheng007/spike            v2                       c15413ef3f96        About a minute ago   269MB
guozheng007/spike            v1                       83b175b46208        14 hours ago         268MB
guozheng007/dotnetcorecase   v1                       75cf01ec8b62        45 hours ago         265MB
microsoft/dotnet             2.2-aspnetcore-runtime   c56aab97bc42        2 weeks ago          260MB
microsoft/dotnet             2.1-aspnetcore-runtime   81472b549eb2        2 weeks ago          253MB
[root@localhost publish]# docker run --name spikev2 -d guozheng007/spike:v2
f4ebc38ce3b2b0de7e2a6bb1f8272de53a918fcf6921d859363ae1ef295853f6

 

 上面的操作是把該容器已經啟動起來了,容器執行成功之後,會返回一個標識。

(5)檢視容器是否正在啟動: docker ps

[root@localhost publish]# docker run --name spikev2 -d guozheng007/spike:v2
f4ebc38ce3b2b0de7e2a6bb1f8272de53a918fcf6921d859363ae1ef295853f6
[root@localhost publish]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4ebc38ce3b2 guozheng007/spike:v2 "dotnet Spike.Api.dll" 2 minutes ago Up 2 minutes 80/tcp spikev2

 

[root@localhost publish]# docker top spikev2
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                4131                4114                0                   10:26               ?                   00:00:01            dotnet Spike.Api.dll

 

[root@localhost publish]# ps -ef | grep dotnet
root       4131   4114  0 10:26 ?        00:00:01 dotnet Spike.Api.dll
root       4520   2936  0 10:33 pts/1    00:00:00 grep --color=auto dotnet

 

(6)現在,我們確認容器和應用程式都執行起來了,那如何訪問呢?如何檢視容器的IP和Port

docker inspect spikev2

[root@localhost publish]# docker inspect spikev2
[
    "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "ASPNETCORE_URLS=http://+:80",
                "DOTNET_RUNNING_IN_CONTAINER=true",
                "ASPNETCORE_VERSION=2.1.11"
            ],
            "Cmd": [
                "dotnet",
                "Spike.Api.dll"
            ],
            "ArgsEscaped": true,
            "Image": "guozheng007/spike:v2",
            "Volumes": null,
            "WorkingDir": "/data",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "maintainer": "[email protected]"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "0ccb6f368934d4cf211e0529813b22261a39d663e34008de8ea72cb201f937d0",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "80/tcp": null
            },
            "SandboxKey": "/var/run/docker/netns/0ccb6f368934",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "4008bc70feca0a7d6bd361dd5f57650acec344ec0ff5dcb44a0f032d48823731",
            "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": "70585ed93ba6d331c470379fe48ed81d80afe769543cdddcc3b44a58556bed5b",
                    "EndpointID": "4008bc70feca0a7d6bd361dd5f57650acec344ec0ff5dcb44a0f032d48823731",
                    "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
                }
            }
        }
    }
]

 

從上面的資訊可以看出,對外暴露的埠號是80  IP地址是172.17.0.2

[root@localhost publish]# docker logs spikev2
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {345c33be-ab36-488a-84a2-81739761e037} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /data
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.

 接下來讓我們訪問一把:

 

不要走,客官,故事還沒講完,繼續往後看。

 

五、總結

最後,我把實驗的過程遇到的問題總結一下。

(1)在構建映象和容器的時候,名字要小些,不能大寫。

 (2)在手動用vs釋出的時候,遇到的問題  An assembly specified in the application dependencies manifest (xxx.deps.json) was not found

解決辦法,請參考這篇部落格:https://blog.csdn.net/ArthurRen0803/article/details/80875019

(3)在啟動Docker時Centos7.3遇到:IPv4 forwarding is disabled. Networking will not work

解決辦法,請參考一下內容

https://stackoverflow.com/questions/24756240/how-can-i-use-iptables-on-centos-7

英文看不懂的看這個  https://www.jianshu.com/p/82067b8c0190

https://blog.slogra.com/post-740.html

(4)Centos7.3遇到:Failed to start iptables.service: Unit iptables.service failed to load

解決辦法:https://www.cnblogs.com/faunjoe88/p/7003815.html

(5)關於Dockerfile的問題,如果遇到一下問題,可參考下面的解決辦法

 

六、最後再補充一點關於Dockerfile的最佳實踐例子

關鍵字

(1)From centos

儘量使用官方的image最為base image ,原因很簡單 就是維了安全。

(2)LABEL

最佳實踐:metadata 必不可少

(3)RUN

最佳實踐:我們要知道,每執行一次RUN都會生成一層,為了美觀,複雜的run請用反斜線換行,避免無用分層,合併多條命名為一行!!!

(4)設定當前工作目錄 WORKDIR

最佳實踐:用WORKDIR,不要用RUN cd  ,儘量是用絕對目錄。

(5)都是將本地的一些檔案新增到docker image中,不同的一點是,ADD在新增壓縮包時,不僅會新增到指定目錄,而且還會解壓。

最佳實踐:(新增本地檔案是可以使用ADD  COPY   新增遠端檔案時 使用 curl 或者 wget),大多數情況下COPY優於ADD ,ADD 處理COPY還有解壓的功能

(6)ENV

儘量是用ENV增加可維護性

好了,暫時講到這裡,希望對你有幫助。

 

參考文章:

一線碼農:https://www.cnblogs.com/huangxincheng/p/10391829.html

麥兜搞IT:《系統學習Docker 踐行DevOps理念》

 

 

 

作者:郭崢

出處:http://www.cnblogs.com/runningsmallguo/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。