• asp.net core+mysql+nginx容器化部署


    使用docker进行容器化部署和运维近两年时间了,有必要做个总结记录。这里从零开始由浅入深,最终完成asp.net core+mysql+nginx的容器化部署。

    一、常用基础命令

    查看镜像

    docker images

    查看容器

    docker ps -a

    查看容器内部详细信息

    docker inspect <容器id/名称>

    查看容器的ip

    docker inspect <容器id/名称> | grep IPAddress

    启停容器

    docker start/stop/restart <容器id/名称>

    删除容器

    docker rm <容器id/名称>

    删除所有容器

    docker rm $(docker ps -qa)

    删除镜像

    docker rmi <镜像id/名称>

    docker image rm <镜像id/名称>

    查看容器日志

    docker logs -f -t --tail 30 <容器id/名称>

    -t,加入时间戳
    -f,跟随最新的日志打印
    --tail 数字n,显示最后n行

    进入容器

    docker exec -it <容器id/名称> /bin/bash

    打包镜像。
    如将当前目录打包成镜像,并命名为hello

    docker build -t <镜像名称> <路径> 

    docker build -t hello .

    运行镜像。
    如运行hello镜像,创建并运行容器hello-1

    docker run --name <容器名称> -d -p 80:5000 <镜像名称>

    docker run --name hello-1 -d -p 80:5000 hello 

    -d,为后台任务形式运行,
    -p,指定端口映射,本地端口:容器端口

    修改容器后,提交生成一个新的镜像。
    如将id:9a0c3f的容器提交为新的镜像hello:v1.0.1

    docker commit <容器id/名称> <新的镜像名称[:tag]>

    docker commit 9a0c3f hello:v1.0.1

    查询默认镜像站点的镜像。
    比如查询mysql相关镜像。
    docker search <镜像名称> 

    docker search mysql 

    查询mysql镜像历史版本

    curl https://registry.hub.docker.com/v1/repositories/mysql/tags | tr -d '[[]" ]' | tr '}' ' ' | awk -F: -v image='mysql' '{if(NR!=NF && $3 != ""){printf("%s:%s ",image,$3)}}'

    二、Docker工具、镜像、Demo项目 

    2.1 Docker工具

    这里用到docker和docker-compose两个工具,安装过程不做赘述,仅展示测试的版本。

    [app@test /]$ docker --version
    Docker version 19.03.4, build 9013bf583a
    [app@test /]$ docker-compose --version
    docker-compose version 1.22.0, build f46880fe

    2.2 镜像

    这里用到mysql,nginx,asp.net core三个镜像。 

    其中的mysql和nginx镜像直接通过命令 docker pull mysql和 docker pull nginx,从默认的docker镜像站点registry.hub.docker.com下载最新版本即可。 

    asp.net core的镜像获取方式则略有不同,2018 年5月之后,微软将所有docker image都推送到了 MCR(Miscrosoft Container Registry),官方地址https://github.com/microsoft/containerregistry。按照官方说法,目前已经对全球多区域进行负载均衡以提供对MCR目录的可靠一致性访问,换句话说,不需要设置docker仓库地址等从各种国内镜像加速去下载了,我试验了下速度的确很快。

    mcr仓库列表地址:https://mcr.microsoft.com/v2/_catalog,找到asp.net core的仓库为 dotnet/core/aspnet 

    某个仓库内tags查询方式:
    https://mcr.microsoft.com/v2/{namespace/repo}/tags/list
    对应我们要查找的tag地址为:
    https://mcr.microsoft.com/v2/dotnet/core/aspnet/tags/list

    而mcr镜像下载的命令格式为:
    docker pull mcr.microsoft.com/<namespace/repo>:<tag> 

    相应的我们下载asp.net core v3.1.1镜像的命令最终就是:
    docker pull mcr.microsoft.com/dotnet/core/aspnet:3.1.1 

    当然,我们也可以直接在dockerhub进行搜索asp.net,直接获得下载命令。搜索链接为
    https://hub.docker.com/search?q=asp.net&type=image

     可以看到主要有三个镜像,分别为

    ASP.NET,对应dotnet framework的版本镜像
    docker pull mcr.microsoft.com/dotnet/framework/aspnet
    docker pull mcr.microsoft.com/dotnet/framework/aspnet:4.8
    docker pull mcr.microsoft.com/dotnet/framework/aspnet:3.5
    
    ASP.NET Core Runtime,对应dotnet core的版本镜像
    docker pull mcr.microsoft.com/dotnet/aspnet
    docker pull mcr.microsoft.com/dotnet/aspnet:5.0
    docker pull mcr.microsoft.com/dotnet/aspnet:3.1
    
    ASP.NET Core 3.1 Runtime属于ASP.NET Core Runtime的一个版本

     最后查看我们的镜像列表,其中 mcr.microsoft.com/dotnet/aspnet:3.1 就是我们要使用的镜像了,它与上面的 mcr.microsoft.com/dotnet/core/aspnet:3.1.1 都是.NET Core runtime,都不包括.NET Core SDK,仅仅版本有微小差别。

    [app@test /]$ docker images
    REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
    nginx                                  latest              ad4c705f24d3        10 days ago         133MB
    mysql                                  latest              0716d6ebcc1a        2 weeks ago         514MB
    mcr.microsoft.com/dotnet/core/aspnet   3.1.1               e28362768eed        19 months ago       207MB
    mcr.microsoft.com/dotnet/aspnet        3.1                 5d1ca8ae6edb        6 days ago          208MB
    #mcr.microsoft.com/dotnet/core/aspnet:3.1.1镜像的容器内查看dotnet版本
    root@490d942232fd:/app# dotnet --info It was not possible to find any installed .NET Core SDKs Did you mean to run .NET Core SDK commands? Install a .NET Core SDK from: https://aka.ms/dotnet-download Host (useful for support): Version: 3.1.1 Commit: a1388f194c .NET Core SDKs installed: No SDKs were found. .NET Core runtimes installed: Microsoft.AspNetCore.App 3.1.1 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.1 [/usr/share/dotnet/shared/Microsoft.NETCore.App] To install additional .NET Core runtimes or SDKs: https://aka.ms/dotnet-download
    #mcr.microsoft.com/dotnet/aspnet:3.1镜像的容器内查看dotnet版本
    root@cc2dad7798b3:/app# dotnet --info It was not possible to find any installed .NET Core SDKs Did you mean to run .NET Core SDK commands? Install a .NET Core SDK from: https://aka.ms/dotnet-download Host (useful for support): Version: 3.1.19 Commit: aae002469c .NET Core SDKs installed: No SDKs were found. .NET Core runtimes installed: Microsoft.AspNetCore.App 3.1.19 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.19 [/usr/share/dotnet/shared/Microsoft.NETCore.App] To install additional .NET Core runtimes or SDKs: https://aka.ms/dotnet-download

    镜像仅仅包括runtime,不包括sdk,这样体积会比较小,当然  dotnet restore,dotnet run,dotnet publish 等sdk命令也就无法使用了,我们应在容器外进行 dotnet publish ,并将发布目录挂载共享到容器中构建运行。

    2.3 Demo项目 

    编写了简单的asp.net core mvc+mysql 的测试项目,已提交https://github.com/gitsongs/docker-demo,可以直接下载使用。

    git clone https://github.com/gitsongs/docker-demo.git 

    三、通过Dockerfile打包镜像

    3.1 共享挂载卷

    docker容器内部与宿主机是隔离的,如果我们运行asp.net core容器,并且每次进入容器里面部署源代码,这样很不方便,再者每次提交更新部署还要反复生成新的镜像也比较麻烦和耗时,如不提交镜像,容器一旦销毁那么容器内做的工作和数据就会丢失。而docker提供了挂载卷共享的功能,可以很好的应对这一问题。而且对于挂载卷目录或文件,对宿主机的文件修改会反应到容器内,反之对于容器内共享目录的文件修改不会影响到宿主机上,这体现了容器的隔离特性。这一功能在运维部署时可以用来持续构建(CI),基本思路是,首先通过git更新源码到宿主机上进行编译发布,然后将发布同步到挂载卷目录,最后在容器中构建运行,针对这个后续会单独写一篇文章进行详细介绍。

    可以通过docker run命令中增加  -v <host目录:容器目录>  参数挂载共享卷。
    docker run -it -v $HOME/docker-demo:/app mcr.microsoft.com/dotnet/core/aspnet:3.1.1 

    这样容器内的/app目录就对应的是宿主机的 $HOME/docker-demo 目录了。

    也可以通过后续的Dockerfile 或 docker-compose.yml 进行指定。

    3.2 数据挂载卷

    除了上述的共享宿主机目录的挂载卷,还有数据卷。比如mysql容器,一旦容器销毁,那么我们的数据库数据就会丢失,为了应对这种情形,可以创建数据卷,然后挂载到容器中以进行容器数据的持久化,这样即便容器销毁,数据卷可以保留。

    #创建数据卷
    $ docker volume create --name demo.db
    #查找数据卷文件
    $ find / -name "demo.db"
    /var/lib/docker/volumes/demo.db
    #查看数据卷信息
    $ docker volume inspect demo.db
    [
        {
            "Name": "demo.db",
            "Driver": "local",
            "Mountpoint": "/var/lib/docker/volumes/demo.db/_data",
            "Labels": {},
            "Scope": "local"
        }
    ]
    # 挂载数据卷启动MySql实例
    $ docker run --name docker-mysql -v demo.db:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql

    3.3 编辑Dockerfile

    通过Dockerfile可以指定很多参数,用于打包镜像。比如可以通过挂载共享卷,将代码程序这一变量目录共享到容器中,而容器本质只是提供一个隔离的特定运行环境(下面的例子未采用这种做法)。

    $cd ~/test
    $git clone https://github.com/gitsongs/docker-demo.git
    $cd docker-demo/docker-demo
    $dotnet publish -c Release -o ./publish
    $vim Dockerfile
    $cat Dockerfile
    FROM mcr.microsoft.com/dotnet/aspnet:3.1 WORKDIR /app COPY . /app ENV ASPNETCORE_URLS http://*:8881 ENV ASPNETCORE_ENVIRONMENT Production EXPOSE 8881 ENTRYPOINT /app/docker-netcore.start.sh
    $cat docker-netcore.start.sh
    #!/bin/bash
    echo $(pwd)
    dotnet /app/publish/docker-demo.dll 
    
    int=1
    while(( $int<=100 ))
    do
        echo $int
        sleep 10s
        let "int++"
    done

    这里的Dockerfile,我们指定容器使用镜像 mcr.microsoft.com/dotnet/aspnet:3.1 ,容器工作目录为/app,并将当前上下文目录即宿主机的~/test/docker-demo/docker-demo复制到容器/app目录下,指定了相关环境变量,最后指定容器入口程序为 docker-netcore.start.sh ,文件内容也很简单,就是运行docker-demo程序,在最后面还增加了一段100*10s的耗时程序,是因为入口程序执行完毕后容器就会自动停止运行,这里的耗时程序就是为了在测试过程中,避免一些因素导致docker-demo程序启动失败,容器自动停止,这样我们可以有时间通过交互模式进入容器进行一些排查操作,比如进入容器查看 dotnet --info 或者ping一下其它容器以测试是否联通。

    完成以上工作后,就可以打包镜像了,这里将我们的镜像命名为 docker-netcore-image 。
    docker build -t docker-netcore-image . 

    3.4 启动容器

    接下来我们通过上面的镜像 docker-netcore-image 创建一个容器 docker-netcore 。查看项目docker-demo文件 appsettings.json ,可知项目依赖访问mysql数据库 docker-mysql ,所以要先创建一个mysql镜像的容器 docker-mysql ,而且两个容器要联通。

    $ cat appsettings.json 
    ...
      "ConnectionStrings": {
        "MySql": "server=docker-mysql;database=DemoDb;uid=root;pwd=123456;"
      }
    ...

    具体操作过程如下:

    # 创建容器网络,以联通两个容器
    $ docker network create -d bridge docker-net-test
    # 查看容器网络
    $ docker network ls
    # 创建容器docker-mysql
    $ docker run --name docker-mysql -d --network docker-net-test -e MYSQL_ROOT_PASSWORD=123456 mysql
    # 创建容器
    $ docker run --name docker-netcore -d --network docker-net-test docker-netcore-image
    # 查看容器
    $ docker ps -a
    # 进入容器
    $ docker exec -it docker-netcore /bin/bash
    # 安装ping
    $ apt-get update
    $ apt install iputils-ping
    # 测试与docker-mysql是联通的
    $ ping docker-mysql
    # 一切正常,测试项目,返回json结果
    $ curl localhost:8881/home/test
    [{"id":1,"name":"u5F20u4E09","sex":"u7537","birthday":"2000-08...}]

     四、通过docker-compose完成asp.net core+mysql+nginx容器化部署

    docker-compose就像是容器的管家,用于定义和运行多容器。其使用yml文件来配置所有容器,最后使用一个命令就可以根据yml文件配置创建并启动所有容器服务。

    我们的最终目的就是运行三个容器服务,使用docker-compose就会非常方便快捷,没有必要打包镜像再去运行。

    配置docker-compose内容如下:

    version: '2.2'
    services:
      docker-mysql-service:
        container_name: docker-mysql
        image: mysql
        environment:
          MYSQL_ROOT_PASSWORD: 123456
        volumes:
          - ./mysql:/var/lib/mysql
    
      docker-netcore-service:
        container_name: docker-netcore
        build: .
        working_dir: /app
        depends_on:
          - docker-mysql-service
        links:
          - docker-mysql-service
        environment:
          - ASPNETCORE_URLS=http://0.0.0.0:8881
          - ASPNETCORE_ENVIRONMENT='Production'
        image: mcr.microsoft.com/dotnet/aspnet:3.1
        ports:
          - "127.0.0.1:8881:8881"
        volumes:
          - ~/test/docker-demo/docker-demo:/app
          - /etc/localtime:/etc/localtime
        entrypoint: /app/docker-netcore.start.sh
      
      reverse-proxy-service:
        container_name: docker-nginx
        image: nginx
        depends_on:
          - docker-netcore-service
        ports:
          - "5050:8080"
        volumes:
          - ./proxy.conf:/etc/nginx/conf.d/default.conf

    配置nginx的proxy.conf内容如下:

    server {
        listen 8080;
        location / {
          proxy_pass http://docker-netcore-service:8881;
        }
    }

    最终操作过程:

    $ docker-compose up -d
    Creating network "docker-demo_default" with the default driver
    Creating docker-mysql ... done
    Creating docker-netcore ... done
    Creating docker-nginx   ... done
    $ docker ps -a
    CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS              PORTS                            NAMES
    10be2df533b0        nginx                                 "/docker-entrypoint.…"   15 seconds ago      Up 14 seconds       80/tcp, 0.0.0.0:5050->8080/tcp   docker-nginx
    d2699558111a        mcr.microsoft.com/dotnet/aspnet:3.1   "/app/docker-netcore…"   16 seconds ago      Up 15 seconds       127.0.0.1:8881->8881/tcp         docker-netcore
    d907b9c112af        mysql                                 "docker-entrypoint.s…"   17 seconds ago      Up 16 seconds       3306/tcp, 33060/tcp              docker-mysql
    $ curl localhost:5050/home/test [{"id":1,"name":"u5F20u4E09","sex":"u7537","birthday":"2000-08-15..."}]
  • 相关阅读:
    赤羽西二丁目14号
    080520 雨 大风
    游泳的梦
    poj1088 滑雪 解题报告
    sgu 183. Painting the balls 动态规划 难度:3
    POJ 1947 Rebuilding Roads 树形dp 难度:2
    POJ 2566 Bound Found 尺取 难度:1
    hdu4800 Josephina and RPG 解题报告
    POJ 2057 The Lost Home 树形dp 难度:2
    HDU 4791 Alice's Print Service 思路,dp 难度:2
  • 原文地址:https://www.cnblogs.com/jiujiduilie/p/15310659.html
Copyright © 2020-2023  润新知