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证书
-
创建相应的文件夹
#创建对应的目录 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
-
创建nginx主配置文件,因为后面挂载时指定的是具体的配置文件,所以需要先创建一个nginx.conf文件
touch /usr/local/docker/nginx_docker/conf/nginx.conf
-
复制以下内容,这是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; }
-
创建nginx引用配置文件,其他新增配置文件可以放在
/usr/local/docker/nginx_docker/conf.d
中,以.conf
结尾就行touch /usr/local/docker/nginx_docker/conf.d/default.conf
-
复制以下内容,添加此配置文件是为了启动容器之后,能正常访问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; } }
-
启动容器并挂载
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 宿主机路径:容器内路径 表示将容器内路径挂载到宿主机路径
-
执行完成后, 测试启动是否成功,有返回说明是成功的
curl http://localhost:8080
-
查看日志情况,发现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
-
创建文件夹
mkdir -p /usr/local/docker/mysql_docker/conf mkdir -p /usr/local/docker/mysql_docker/data
-
执行启动命令
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
-
修改配置文件,可以在宿主机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
-
创建文件夹
mkdir -p /usr/local/docker/tomcat_docker/webapps mkdir -p /usr/local/docker/tomcat_docker/conf mkdir -p /usr/local/docker/tomcat_docker/logs
-
创建配置文件
- 由于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>
-
指定启动命令
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
-
测试运行
启动失败可以使用
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
-
创建文件夹
mkdir -p /usr/local/docker/redis/data
-
创建配置文件
- 创建配置文件
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
-
指定启动命令
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
-
测试运行
查看正在运行的容器
docker ps
如果启动失败可以使用
docker logs -f -t --tail 100 容器ID或容器名
直接打印出docker容器中的日志,可以很方便定位问题。
五、总结
docker 安装比较快捷,但是部分镜像内部情况不清楚,导致出现问题比较难定位,我们可以自己制作基础镜像。当然现在已经不会再单独制作一个tomcat镜像了,镜像可以是一个更完整的软件,其实docker镜像就是一种轻量级、可执行的软件包,用来打包软件运行环境和运行基于环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时,库、环境变量和配置文件等。以后springboot项目都可以直接将tomcat和java环境,连同项目等一并打包成一个镜像,然后直接docker run运行就行,非常快捷。