Docker部署应用

上一章了解了Docker容器数据卷,现在所有准备工作都就绪了,现在可以尝试部署各类应用了,如nginx,tomcat,mysql等

其实通过Docker部署它们还是有很多坑需要注意,下面将会一一填上。

一、Docker部署nginx

1.1 下载镜像

下载nginx镜像时不知道哪个版本稳定,可以到nginx官网查看Stable version

然后通过docker pull nginx:版本号下列即可,如:docker pull nginx:1.20.1

1.2 运行容器

创建启动时,需要将容器中的配置和日志文件挂载到宿主机,所以首先需要知道nginx镜像中它们位置,具体这些位置,在dockerhub

可以找到,可以带着“答案”去找。

  • 首页路径 /usr/share/nginx/html
  • nginx主配置文件路径 /etc/nginx/nginx.conf
  • nginx引用配置文件路径 /etc/nginx/conf.d
  • 日志文件路径 /var/log/nginx
  • cert目录nginx没有,可以提前挂载好,一般存放SSL证书
  1. 创建相应的文件夹

    #创建对应的目录
    mkdir -p /usr/local/docker/nginx_docker/conf
    mkdir -p /usr/local/docker/nginx_docker/conf.d
    mkdir -p /usr/local/docker/nginx_docker/cert
    mkdir -p /usr/local/docker/nginx_docker/logs
    
  2. 创建nginx主配置文件,因为后面挂载时指定的是具体的配置文件,所以需要先创建一个nginx.conf文件

    touch /usr/local/docker/nginx_docker/conf/nginx.conf
    
  3. 复制以下内容,这是nginx主配置文件内容

    user  nginx;
    
    worker_processes  1;
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /etc/nginx/conf.d/*.conf;
    }
    
  4. 创建nginx引用配置文件,其他新增配置文件可以放在/usr/local/docker/nginx_docker/conf.d中,以.conf结尾就行

    touch /usr/local/docker/nginx_docker/conf.d/default.conf
    
  5. 复制以下内容,添加此配置文件是为了启动容器之后,能正常访问nginx首页

    server {
        listen       80;
        server_name  localhost;
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    
        #error_page  404              /404.html;
        # redirect server error pages to the static page /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    
  6. 启动容器并挂载

    docker run -it -d --restart always --privileged=true -p 8080:80 -p 443:443 --name nginx \
    -v /usr/local/docker/nginx_docker/conf/nginx.conf:/etc/nginx/nginx.conf \
    -v /usr/local/docker/nginx_docker/conf.d:/etc/nginx/conf.d \
    -v /usr/local/docker/nginx_docker/cert:/etc/nginx/cert \
    -v /usr/local/docker/nginx_docker/logs:/var/log/nginx nginx:latest
    

    命令解释:

    -it 表示交互运行,相当于有个进程一直连接着nginx,防止它在后台被关闭,这里也可以不加

    -d 表示后台运行

    –restart always 表示docker服务重启时同时启动当前容器

    -p 8080:80 表示宿主机1111端口映射容器暴露出来的80端口,又是会看到-P,这是大写P,表示随机指定端口

    –name nginx 表示容器的名为nginx,注意这个名字不可重复

    -v 宿主机路径:容器内路径 表示将容器内路径挂载到宿主机路径

  7. 执行完成后, 测试启动是否成功,有返回说明是成功的

    curl http://localhost:8080
    
  8. 查看日志情况,发现logs已经多出了两个日志文件,为了更好的查看日志,可以将日志定时切割,具体不在这展示了,可以参考我转载一篇博客:nginx日志切割

二、Docker部署mysql

Docker部署mysql相对简单,以常见的mysql5.7为例

2.1 下载镜像

docker pull mysql:5.7

2.2 运行容器

一般mysql 需要挂载出来的文件

  • mysql配置文件夹引用路径/etc/mysql/conf.d,当然还有其他的配置文件,挂载一个就行
  • mysql的data路径/var/lib/mysql
  1. 创建文件夹

    mkdir -p /usr/local/docker/mysql_docker/conf
    mkdir -p /usr/local/docker/mysql_docker/data
    
  2. 执行启动命令

    docker run -d -p 3334:3306 --name mysql5.7 --restart=always --privileged=true \
    -e MYSQL_ROOT_PASSWORD=123456 \
    -v /usr/local/docker/mysql_docker/conf:/etc/mysql/conf.d \
    -v /usr/local/docker/mysql_docker/data:/var/lib/mysql mysql:5.7
    

    命令和前面类似,特殊命令解释:

    -e MYSQL_ROOT_PASSWORD=123456 表示设置root初始密码为123456

  3. 修改配置文件,可以在宿主机conf文件夹新建一个my.cnf 文件就可以了

    [mysqld]
    sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
    character_set_server = utf8mb4
    

三、Docker部署tomcat

Docker部署tomcat也很简单,以常见的tomcat9.0为例

3.1 下载镜像

docker pull tomcat:9.0

3.2 运行容器

tomcat容器主要需要挂载出来的文件包括webapps,conf,logs对应的路径分别是

  • /usr/local/tomcat/webapps
  • /usr/local/tomcat/conf
  • /usr/local/tomcat/logs
  1. 创建文件夹

    mkdir -p /usr/local/docker/tomcat_docker/webapps
    mkdir -p /usr/local/docker/tomcat_docker/conf
    mkdir -p /usr/local/docker/tomcat_docker/logs
    
  2. 创建配置文件

    • 由于conf下有文件,文件夹,直接宿主机conf对应容器conf挂载总是失败,目前没有好的办法,只能指定挂载某个单独文件
    touch /usr/local/docker/tomcat_docker/conf/server.xml
    
    • 复制以下内容,文件内容就是普通的server.xml内容,只是把注释去除了,

      并将<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>

      改成了<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" secretRequired=""/>

      不改的话,启动会报错Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.

    <?xml version="1.0" encoding="UTF-8"?>
      <Server port="8005" shutdown="SHUTDOWN">
      <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
      <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
      <GlobalNamingResources>
        <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
      </GlobalNamingResources>
      <Service name="Catalina">
        <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" secretRequired=""/>
    
        <Engine defaultHost="localhost" name="Catalina">
    
          <Realm className="org.apache.catalina.realm.LockOutRealm">
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
          </Realm>
    
          <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/>
          </Host>
        </Engine>
      </Service>
    </Server>
    
  3. 指定启动命令

    docker run -d -p 8080:8080 --name tomcat9.0 --restart=always --privileged=true \
    -v /usr/local/docker/tomcat_docker/webapps:/usr/local/tomcat/webapps \
    -v /usr/local/docker/tomcat_docker/conf/server.xml:/usr/local/tomcat/conf/server.xml \
    -v /usr/local/docker/tomcat_docker/logs:/usr/local/tomcat/logs tomcat:9.0
    
  4. 测试运行

    启动失败可以使用docker logs -f -t --tail 100 容器ID或容器名直接打印出docker容器中的日志,方便查找

    运行时,直接访问8080,是404错误,因为tomcat9.0镜像webapps中默认没有文件,tomcat8.0镜像是有点,默认文件都在容器的/usr/local/tomcat/webapps.dist 下,所以需要进入容器,将文件拷贝过去

    [root@izuf67znusfv5r0k1fzac9z conf]# docker exec -it tomcat9.0  /bin/bash
    root@d5f9d828459b:/usr/local/tomcat# cp -r webapps.dist/* webapps
    

    完成之后重启,一直在部署项目,还卡住了,tomcat 启动缓慢,是随机数问题,有两种方式

    • 第一种是改catalina.sh

      catalina.sh 中加入这么一行:-Djava.security.egd=file:/dev/./urandom,这个文件比较好找,所以我先改了这个,但是改完之后,启动很慢,并且报了错,/usr/local/tomcat/bin/catalina.sh: line 127: -Djava.security.egd=file:/dev/./urandom: No such file or directory,所以我使用了第二种

    • 第二种改java.security

      在 java.security中的securerandom.source=file:/dev/random改成securerandom.source=file:/dev/./urandom就行了,试到这,我已经吐了主要是这个镜像,它把这个文件放在jdk的conf/security,找了半天。为了以后启动方便,后面会使用dockerfile制作自己的tomcat镜像,并提交到自己的dockerhub或者是阿里云镜像仓库中方便下载。

    mkdir -p /usr/local/docker/tomcat_docker/bin
    #将java.security文件复制出来
    docker cp a0c72e5695a7:/usr/local/openjdk-11/conf/security/java.security /usr/local/docker/tomcat_docker/bin/java.security
    #宿主机到容器
    docker cp /usr/local/docker/tomcat_docker/bin/java.security a0c72e5695a7:/usr/local/openjdk-11/conf/security/java.security
    #重启容器,这里我重启了10次,因为想感受一下成功的快乐
    docker restart tomcat9.0
    

四、Docker部署redis

Docker部署redis,以最新版为例

4.1 下载镜像

docker pull redis

4.2 运行容器

redis容器主要需要挂载出来的文件包括conf,data对应的路径分别是

  • /etc/redis

  • /data

  1. 创建文件夹

    mkdir -p /usr/local/docker/redis/data  
    
  2. 创建配置文件

    • 创建配置文件
    touch /usr/local/docker/redis/redis.conf
    
    • 复制以下内容
    port 6379
    daemonize no
    tcp-keepalive 300
    databases 16
    save 10 2
    rdbcompression yes
    dbfilename dump-6379.rdb
    appendonly yes
    appendfilename appendonly-6379.aof
    #如果需要外网访问可以加上下面的配置
    bind 0.0.0.0
    requirepass 密码
    protected-mode no
    
  3. 指定启动命令

    docker run -p 56380:6379 --name redis \
    -v /usr/local/docker/redis/redis.conf:/etc/redis/redis.conf \
    -v /usr/local/docker/redis/data:/data \
    -d redis redis-server /etc/redis/redis.conf
    
    
  4. 测试运行

    查看正在运行的容器

    docker ps
    

    如果启动失败可以使用docker logs -f -t --tail 100 容器ID或容器名直接打印出docker容器中的日志,可以很方便定位问题。

五、总结

docker 安装比较快捷,但是部分镜像内部情况不清楚,导致出现问题比较难定位,我们可以自己制作基础镜像。当然现在已经不会再单独制作一个tomcat镜像了,镜像可以是一个更完整的软件,其实docker镜像就是一种轻量级、可执行的软件包,用来打包软件运行环境和运行基于环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时,库、环境变量和配置文件等。以后springboot项目都可以直接将tomcat和java环境,连同项目等一并打包成一个镜像,然后直接docker run运行就行,非常快捷。