docker容器化实战
前后端分离系统
前端 https://gitee.com/yuco/eladmin-web.git
后端 https://gitee.com/yuco/eladmin.git
- 要素:
vuenpmspringbootmysqlredis
java后端容器化
可以先完全从零手工部署,理解手工部署到改造为Dockerfile的过程。
思路:
- java项目,采用mvn进行构建,最终生成jar包,拷贝到jdk环境中启动即可,因此使用多阶构建
- 手动构建验证
# 1.进入maven环境,下载代码,构建得到jar包,pom.xml已经配置好了阿里云的mvn源
docker run --rm -ti aerialist7/maven-git sh
git clone https://gitee.com/yuco/eladmin.git
mvn clean package
下一步,只需要创建一个有jdk的环境,运行jar包即可,占空间很小。
利用多阶段构建思路,即可启动后端java了
FROM aerialist7/maven-git as builder
WORKDIR /opt/eladmin
COPY . .
RUN mvn clean package
FROM java:8u111
WORKDIR /opt/eladmin
COPY --from=builder /opt/eladmin/eladmin-system/target/eladmin-system-2.6.jar .
CMD [ "sh", "-c", "java -Dspring.profiles.active=prod -jar eladmin-system-2.6.jar" ]
如上的java参数-Dspring.profiles.active=prod是指可以有多个config.yml配置文件,以在不同的环境下测试。
在该代码中,配置文件路径是
[root@es-node1 ~/devops-docker/eladmin]#tree eladmin-system/src/main/resources/
eladmin-system/src/main/resources/
├── banner.txt
├── config
│ ├── application-dev.yml
│ ├── application-prod.yml
│ └── application.yml
├── generator.properties
├── log4jdbc.log4j2.properties
├── logback.xml
└── template
├── email
│ ├── email.ftl
│ └── taskAlarm.ftl
└── generator
├── admin
│ ├── Controller.ftl
│ ├── Dto.ftl
│ ├── Entity.ftl
│ ├── Mapper.ftl
│ ├── QueryCriteria.ftl
│ ├── Repository.ftl
│ ├── Service.ftl
│ └── ServiceImpl.ftl
└── front
├── api.ftl
└── index.ftl
6 directories, 19 files
构建镜像
docker build . -t eladmin:v1 -f Dockerfile.multi
数据库部署
该后端用到了mysql,redis,需要我们自行部署
docker run -d -p 3306:3306 --name mysql -v /opt/mysql:/var/lib/mysql -e MYSQL_DATABASE=eladmin -e MYSQL_ROOT_PASSWORD=www.yuchaoit.cn mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
#测试
[root@es-node1 ~/devops-docker/eladmin]#docker exec -it mysql bash
root@c23e52263a3f:/# mysql -uroot -pwww.yuchaoit.cn
mysql数据导入
[root@es-node1 ~/devops-docker/eladmin/sql]#docker cp eladmin.sql mysql:/tmp/
Preparing to copy...
Copying to container - 32.77kB
Copying to container - 51.2kB
Successfully copied 51.2kB to mysql:/tmp/
[root@es-node1 ~/devops-docker/eladmin/sql]#docker exec -it mysql bash
root@c23e52263a3f:/# mysql -uroot -pwww.yuchaoit.cn eladmin < /tmp/eladmin.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
完事可以用navicat验证
redis启动
[root@es-node1 ~/devops-docker/eladmin]#docker run -p 6379:6379 -d --name redis --restart=always redis:3.2 redis-server
192265143f4ec605cc38db2a750b1aa5186911c6fd2b7bb1e39b5444dd41631b
[root@es-node1 ~/devops-docker/eladmin]#docker exec -it redis bash
root@192265143f4e:/data# redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
后端启动
# 后端
docker run --name eladmin-api -d -p 8000:8000 -e DB_HOST=10.0.0.18 -e DB_USER=root -e DB_PWD=www.yuchaoit.cn -e REDIS_HOST=10.0.0.18 eladmin:v1
# 注意看日志
[root@es-node1 ~]#docker logs -f eladmin-api
# 如下是正确
elAdmin- 2023-03-04 13:14:09 [main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.2) 'quartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
elAdmin- 2023-03-04 13:14:09 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'quartzScheduler' initialized from an externally provided properties instance.
elAdmin- 2023-03-04 13:14:09 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.2
elAdmin- 2023-03-04 13:14:09 [main] INFO org.quartz.core.QuartzScheduler - JobFactory set to: org.springframework.scheduling.quartz.SpringBeanJobFactory@6b52dd31
elAdmin- 2023-03-04 13:14:10 [main] INFO o.s.s.web.DefaultSecurityFilterChain - Will not secure any request
elAdmin- 2023-03-04 13:14:10 [main] INFO me.zhengjie.config.RedisConfig - 初始化 -> [Redis CacheErrorHandler]
elAdmin- 2023-03-04 13:14:11 [main] INFO o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8000"]
elAdmin- 2023-03-04 13:14:11 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8000 (http) with context path ''
elAdmin- 2023-03-04 13:14:11 [main] INFO o.s.s.quartz.SchedulerFactoryBean - Starting Quartz Scheduler now
elAdmin- 2023-03-04 13:14:11 [main] INFO org.quartz.core.QuartzScheduler - Scheduler quartzScheduler_$_NON_CLUSTERED started.
elAdmin- 2023-03-04 13:14:11 [main] INFO me.zhengjie.AppRun - Started AppRun in 6.558 seconds (JVM running for 6.986)
elAdmin- 2023-03-04 13:14:11 [main] INFO m.z.modules.quartz.config.JobRunner - Timing task injection complete
前端Vue构建
思路:
- 前端构建需要node环境,构建结果通常为dist静态文件,项目运行仅需要web服务器即可。因此采用多阶构建
- 确认基础镜像:
docker search vue-node - 验证构建,最终采用
codemantn/vue-node作为基础镜像
备注,修改npm源加速
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
npm config set registry https://registry.npm.taobao.org
npm install
npm run build:prod
- 运行环境采用
nginx:alpine作为基础镜像,启动容器熟悉镜像的启动目录等信息 - 把构建的
dist静态文件夹拷贝到镜像的/usr/share/nginx/html/即可
因此,综合得到多阶构建的Dockerfile,最终得到运行的nginx,以及前端页面
FROM codemantn/vue-node AS builder
LABEL maintainer="yc_uuu@163.com"
# config npm
RUN npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/ && \
npm config set registry https://registry.npm.taobao.org
WORKDIR /opt/eladmin-web
COPY . .
# build
RUN ls -l && npm install && npm run build:prod
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
COPY --from=builder /opt/eladmin-web/dist /usr/share/nginx/html/
EXPOSE 80
前端配置文件
用户 > 前端 > 后端
该配置文件,就是指定后端运行的地址。
例如获取生成验证码的接口。http://10.0.0.18:8000/auth/code
[root@es-node1 ~/devops-docker/eladmin-web]#cat .env.production
ENV = 'production'
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置
# 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http
VUE_APP_BASE_API = 'http://10.0.0.18:8000'
# 如果接口是 http 形式, wss 需要改为 ws
VUE_APP_WS_API = 'ws://10.0.0.18:8000'
[root@es-node1 ~/devops-docker/eladmin-web]#
构建
docker build . -t eladmin-web:v1 -f Dockerfile
启动前端
# 前端
docker run --name eladmin-web -d -p 80:80 eladmin-web:v1
检查java前后端的启动
[root@es-node1 ~/devops-docker/eladmin-web]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2c147cad333f eladmin-web:v1 "/docker-entrypoint.…" 15 minutes ago Up 15 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp eladmin-web
74387a119bc0 eladmin:v1 "sh -c 'java -Dsprin…" 26 minutes ago Up 26 minutes 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp eladmin-api
192265143f4e redis:3.2 "docker-entrypoint.s…" 44 minutes ago Up 44 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis
c23e52263a3f mysql:5.7 "docker-entrypoint.s…" 48 minutes ago Up 48 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
[root@es-node1 ~/devops-docker/eladmin-web]#
测试访问

验证码是前端正确连接后端后的结果,出不来就是部署有错。
登录后

测试web功能
修改如用户信息
检验前端、后端、数据库的正确连通性。

数据库检查

Python应用容器化
https://gitee.com/yuco/python_demo.git 后端python源码
部署架构
- python3 + django + uwsgi + nginx + mysql
- 内部服务端口8002
思考镜像优化原则
等你彻底理解如下几个规则,就知道如何优化镜像了
- 不必要的内容不要放在镜像中
- 减少不必要的层文件,例如多条linux命令,合并一条RUN
- 减少网络传输操作,尽可能少的,如curl,wget等
- 可以适当的包含一些调试命令,如ps,ss等基础环境的加入,否则难以维护
但是是否优化,也看你对该语言是否需要优化,如减少编译过程,减少系统依赖安装过程
参考(制作一个基础镜像,如直接python3镜像,如bitnami/python 经过验证的)
django-alpine镜像
alpine-python
自己制作
基本Dockerfile
# This my first django Dockerfile
# Version 1.0
# Base images 基础镜像
FROM centos:centos7.5.1804
#MAINTAINER 维护者信息
LABEL maintainer="yc_uuu@163.com"
#ENV 设置环境变量
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
#RUN 执行以下命令
RUN curl -so /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo && rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
RUN yum install -y python36 python3-devel gcc pcre-devel zlib-devel make net-tools nginx
#工作目录
WORKDIR /opt/myblog
#拷贝文件至工作目录
COPY . .
# 拷贝nginx配置文件
COPY myblog.conf /etc/nginx
#安装依赖的插件
RUN pip3 install -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r requirements.txt
RUN chmod +x run.sh && rm -rf ~/.cache/pip
#EXPOSE 映射端口
EXPOSE 8002
#容器启动时执行命令
CMD ["./run.sh"]
构建镜像
docker build . -t myblog:v1 -f Dockerfile
启动数据库
[root@es-node1 ~/devops-docker/python-demo]#docker exec -ti mysql bash
root@c23e52263a3f:/# mysql -uroot -pwww.yuchaoit.cn
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 5.7.36 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database myblog;
Query OK, 1 row affected (0.00 sec)
mysql>
启动django程序
docker run -d -p 8002:8002 --name myblog -e MYSQL_HOST=10.0.0.18 -e MYSQL_USER=root -e MYSQL_PASSWD=www.yuchaoit.cn myblog:v1
# 数据库迁移
## migrate
$ docker exec -ti myblog bash
#/ python3 manage.py makemigrations
#/ python3 manage.py migrate
#/ python3 manage.py createsuperuser
# 超级用户yuchao yuchao123
[root@94ea247ad303 myblog]# python3 manage.py createsuperuser
用户名 (leave blank to use 'root'): yuchao
电子邮件地址: yc_uuu@163.com
Password:
Password (again):
Superuser created successfully.
[root@94ea247ad303 myblog]#
## 收集静态文件
## $ docker exec -ti myblog python3 manage.py collectstatic
访问django文章页

访问django后台
