最近有个课程项目,需要部署到服务器上,免费领取了阿里云两个月的云服务器,记录一下部署过程
Xshell连接到阿里云主机,下载docker
yum install docker-ce
有可能会报错:
Problem: package docker-ce-3:20.10.1-3.el7.x86_64 requires containerd.io >= 1.4.1, but none of the providers can be installed
这是由于需要1.4.1版本以上的containerd.io,默认是安装1.2.0-3.el7
版本,需要自己改
yum install https://download.docker.com/linux/centos/8/x86_64/stable/Packages/containerd.io-1.4.3-3.1.el8.x86_64.rpm
安装好了之后重新安装docker,启动docker
systemctl start docker #启动docker
systemctl enable docker #设置开机自启
可以通过vi /etc/docker/daemon.json
并添加其他源:
{
"registry-mirrors" : [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"https://cr.console.aliyun.com/"
]
}
重启docker服务systemctl restart docker.service
,加快docker拉取速度
首先创建数据挂载点:
docker volume create mysql_data
启动数据库容器:
- 这里我把数据库数据放在了数据卷mysql_data下,不指定绝对路径的话,默认挂载在/var/lib/docker/volumes/目录下
- /var/lib/mysql是mysql容器内部存放mysql数据的地方
- 逻辑就是:将mysql容器内部/var/lib/mysql目录下的容器放在宿主机的/var/lib/docker/volumes/mysql_data目录下
docker run -d --name mysql -p 3306:3306 -v mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
docker exec -it mysql bash
进入容器
mysql -uroot -p123456
进入mysql
执行GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'WITH GRANT OPTION;
刷新FLUSH PRIVILEGES;
navicat 服务器ip + 3306端口远程连接测试,测试成功即可,有可能这时候会失败,是因为服务器没有开放3306端口
我用的是阿里云,点击安全组,然后配置安全组添加即可
docker run --name redis -v redis_data:/data -d -p 6379:6379 redis redis-server --requirepass "123456" --appendonly yes
其他容器过程类似,此处省略
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
@Bean
public FilterRegistrationBean filterRegistration() {
FilterRegistrationBean<RewriteFilter> registration = new FilterRegistrationBean<>();
//注册rewrite过滤器
registration.setFilter(new RewriteFilter());
registration.addUrlPatterns("/*");
registration.addInitParameter(RewriteFilter.REWRITE_TO,"/index.html");
registration.addInitParameter(RewriteFilter.REWRITE_PATTERNS, "/vis/*");
registration.setName("rewriteFilter");
registration.setOrder(1);
return registration;
}
}
/**
* 过滤后端请求,不属于后端的请求,交由前端路由处理
*/
public class RewriteFilter implements Filter {
/**
* 需要rewrite到的目的地址
*/
public static final String REWRITE_TO = "rewriteUrl";
/**
* 拦截的url,url通配符之前用英文分号隔开
*/
public static final String REWRITE_PATTERNS = "urlPatterns";
/** 配置url通配符 */
private Set<String> urlPatterns = null;
private String rewriteTo = null;
@Override
public void init(FilterConfig cfg) throws ServletException {
//初始化拦截配置
rewriteTo = cfg.getInitParameter(REWRITE_TO);
String exceptUrlString = cfg.getInitParameter(REWRITE_PATTERNS);
if (!StringUtils.isEmpty(exceptUrlString)) {
urlPatterns = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(exceptUrlString.split(";", 0))));
} else {
urlPatterns = Collections.emptySet();
}
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
String servletPath = request.getServletPath();
//匹配到后端路径标识,放行,否则,交给前端路由
if (isMatches(urlPatterns, servletPath)) {
req.getRequestDispatcher(rewriteTo).forward(req, resp);
}else{
chain.doFilter(req, resp);
}
}
@Override
public void destroy() {
}
/**
* 匹配返回true,不匹配返回false
* @param patterns 正则表达式或通配符
* @param url 请求的url
* @return
*/
private boolean isMatches(Set<String> patterns, String url) {
if(null == patterns){
return false;
}
for (String str : patterns) {
if (str.endsWith("/*")) {
String name = str.substring(0, str.length() - 2);
if (url.contains(name)) {
return true;
}
} else {
Pattern pattern = Pattern.compile(str);
if (pattern.matcher(url).matches()) {
return true;
}
}
}
return false;
}
}
本机测试,ip + /index.html,成功访问
这种方法不推荐,推荐使用nginx,前后端分离部署,后续(二)中会提到
先clean,再package打包,把生成的jar包和Dockerfile通过xftp发到服务器
Dockerfile:
FROM openjdk:13-alpine3.9
VOLUME /tmp
ADD *.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
docker build -t myImage .
- VOLUME指向了一个/tmp的目录,由于SpringBoot使用内置的Tomcat容器,Tomcat默认使用/tmp作为工作目录。效果就是在主机的/var/lib/docker目录下创建了一个临时文件,并连接到容器的/tmp
- add将项目的jar文件作为app.jar添加到容器
- RUN表示在新创建的镜像中执行一些命令,然后把执行的结果提交到当前镜像。这里使用touch命令来改变文件的修改时间,Docker创建的所有容器文件默认状态都是“未修改”。这对于简单应用来说不需要,不过对于一些静态内容(比如:index.html)的文件就需要一个“修改时间”
- ENTRYPOINT 应用启动命令 参数设定
接着运行容器:
docker run -itd --net=host --name 随意容器名 -p 8088:8088 刚刚创建镜像名
–net=host 告诉 Docker 不要将容器网络放到隔离的名字空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其
它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如
D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用
–privileged=true,容器会被允许直接配置主机的网络堆栈
后续将更新结合nginx的前后端分离部署