• NetCore在Docker中发布及运行


    之前写过一篇关于Docker的文章,回头看了一眼自己差点没有看明白...最近有时间又仔细研究了一遍(主要是生产环境真的要用到了...),顺便从0学习了一下Linux,踩了不少坑。所以准备再写几篇关于Docker的文章。希望对大家有所帮助。

    操作系统为Centos7。项目为asp .netcore webapp。先简单介绍下Docker的安装

    安装

    更新yum包
    sudo yum update
    
    安装需要的软件包, yum-util 提供yum-config-manager功能
    sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    
    设置Docker的yum源
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    
    安装Docker 可以用【:版本号】加在后面安装指定的版本,不加就安装最新版本。安装的docker ce,还有个docker ee,是收费版的
    sudo yum install docker-ce -y
    
    启动docker
    sudo systemctl start docker
    
    使docker服务自动启动
    sudo systemctl enable docker
    
    配置镜像加速
    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://registry.docker-cn.com"]
    }
    EOF
    
    重启docker以使用新的镜像地址
    sudo systemctl daemon-reload
    sudo systemctl restart docker   
    

    构建镜像

    这里就按照官方默认的文件及目录结构来构建镜像和容器,方便了解每个命令的含义

    假设我的项目名称为:myapp1,Dockerfile文件名称为:Dockerfile_myapp1

    目录结构如下

    /mnt/vda1/code/myapp1
    /mnt/vda1/docker/Dockerfile_myapp1
    

    那么构建一个镜像的命令为:

    docker build [选项] <上下文路径/URL/->
    
    sudo docker build -t myapp1:v1 -f /mnt/vda1/docker/Dockerfile_myapp1 /mnt/vda1/code/myapp1 
    
    -t 指定image的名称和版本,不加:v1 则默认版本为latest
    
    -f 指定Dockerfile文件地址 
    
    /mnt/vda1/code/myapp1为镜像构建的**上下文路径**。所谓的上下文就是说在Dokerfile中可以操作的宿主机器的根路径,超出该路径的文件容器中是访问不到的
    

    启动容器

    docker run  -d -p 8001:80 myapp1:v1 --myapp2uri=192.168.3.102 --myapp3uri=myapp3
    
    • -d:指定容器在后台运行
    • -p 8001:80:将容器内的80端口映射到宿主机器上的8001端口
    • 在镜像名称后面的内容则会作为cmd命令传入到程序中

    Dockerfile

    前面的内容很容易理解,Dockerfile文件照葫芦画瓢也可以写一个能用的,但是一旦涉及到功能需求的变化(比如说做自动构建和发布)就头大了。下面我给Dockerfile中常用到的每一个指令结合上面的项目来做一个详细的介绍

    #FROM指定基础镜像,也就是说后面的的WorkDir,Run命令都是在这个镜像的基础上执行的
    #使用sdk2.2执行项目发布 "AS"可以给该镜像起一个别名,可以为build也可以叫做build1,build2 。。。
    FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
    
    #WORKDIR设置容器内的工作目录。该命令之后的命令都已该目录为根目录进行相关的操作
    #当容器启动之后,进入容器会首先进入该目录,容器的根目录为“/“。
    WORKDIR /app1
    
    #COPY将宿主机的文件拷贝到容器中去
    #第一个“./”为上下文的根目录,上下文的定义在上面的镜像构建中提到过,第二个“./”等于/app1(工作目录)
    #此命令将宿主的机的/mnt/vda1/code/myapp1中的所有文件拷贝到容器内的 /app1文件夹下
    COPY ./ ./
    
    #RUN 执行命令行命令
    #生成项目。这里的dotnet命令使用的是上面的sdk:2.2中的dotnet命令
    RUN dotnet build
    
    #发布项目的Release版本到publish文件夹下
    #该命令会在sdk2.2生成的容器中的/app1文件夹下执行
    RUN dotnet publish -c Release -o publish
    
    
    #使用runtime2.2运行项目
    FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
    
    #设置容器内的工作目录
    WORKDIR /app2
    
    #生命准备使用的端口
    EXPOSE 80
    
    #--from=build指定这条命令的上下文是build容器,“./”等于/app2
    COPY --from=build /app1/publish ./
    
    #设置容器内的时区,如果不设置,默认时区是标准时间比北京时间晚8个小时
    RUN echo "Asia/shanghai" > /etc/timezone
    RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    
    #程序入口点。这里的dotnet命令使用的是上面的aspnet:2.2中的dotnet命令
    #该指令的含义是在容器启动时执行dotnet DockerWeb1.dll命令
    #该数组后面还可以继续追加需要的参数,但是为了扩展性及安全性,我们把其余的变量在运行时指定或者在编排工具中指定
    ENTRYPOINT ["dotnet", "myapp1.dll"]
    #CMD命令同样可以实现ENTERPOINT的功能
    #CMD ["dotnet", "myapp1.dll"]
    

    上面的CMD命令被注释掉了,因为CMD很容易被运行时替换掉,拿上面的启动容器的命令来举例:

    如果Dockerfile中使用的是CMD而非ENTRYPOINT,那么启动容器的命令就需要写为:

    docker run -d -p 8001:80 myapp:v1 dotnet myapp1.dll --myapp2uri=192.168.3.102 --myapp3uri=myapp3

    这是因为在myapp:v1后面的命令全是cmd命令,会替换掉Dockerfile中的cmd命令。

    不过在执行CMD命令之前会先执行EnterPoint命令。所以实际的执行顺序为:

    docker run -d -p 8001:80 myapp:v1 [ENTERPOINT] [CMD]

    当然ENTERPOINT也可以被替换,但是并没有替换的必要,因为我们上面的Enterpoint只是指定了一个启动项而已

    Dockerfile中的每一个命令都会生成一层镜像,注意是每一个,有时候还会生成多个。。。这个我还没搞明白。

    所以上面的一个Dokerfile会生成十四五个image,有一些无用了会被删掉,还有一些会作为中间镜像以的名称存在于image中,可以执行docker images -a命令查看

    目前还没有找到自动删除中间层的方法,可以用这个命令进行清理:docker rmi $(docker images --filter dangling=true -q)

    Docker-Compose

    总是通过那么大一长串命令启动容器和构建镜像实在很麻烦,用docker-compose来管理容器和镜像就会方便很多。

    明白了Docker,Docker-compose就容易理解多了。这里只是简单贴一个DockerCompose的配置文件

    version: "3"
    services:
      myapp1:
        #build image的相关操作
        build:
           context: /mnt/vda1/code/myapp1
           dockerfile: /mnt/vda1/docker/Dockerfile_myapp1
        image: myapp1
        restart: always
    	#设置容器名称
    	container_name: myapp1container
        ports:
          - "8001:80"
    	#设置文件夹挂载
        volumes:
          - /mnt/vda1/data/influxexcel:/app/wwwroot/Excels
      myapp2:
        build:
           context: /mnt/vda1/code/myapp2
           dockerfile: /mnt/vda1/docker/Dockerfile_myapp2
        image: myapp2
        restart: always
    	container_name: myapp2container
    	#CMD参数
        command: --ApiUrl1=myapp1container
        ports:
          - "8002:80"
    

    Http连接请求过多问题

    可能报错:Resource temporarily unavailable

    修改 主机
    sysctl -w net.core.somaxconn=32768
    立即生效

    vi /etc/sysctl.conf
    增加一行
    net.core.somaxconn= 32768
    sysctl -p
    重启生效

    同时也要修改docker中的对应参数
    理论上所有docker的连接数不可超过主机的,单个容器不可超过设置的,容器中默认为128个

  • 相关阅读:
    Android 播放音频
    Android Service 入门
    Android ConstraintLayout 说明和例子
    Android LiveData使用
    C# MVC MVP
    shell--4.echo和printf
    shell--3.运算符
    shell--2.shell数组
    mongDB-- 3. 查询操作
    问题--feed列表有新闻重复的问题
  • 原文地址:https://www.cnblogs.com/bluesummer/p/11891190.html
Copyright © 2020-2023  润新知