之前弄过的webNotepad,基于hexo到的博客,已经提供代理的nginx等,在新机上部署时都需要一堆繁琐的配置过程。刚好在看公司项目内网测试环境的docker脚本,于是想试试将之前部署的这些东西都迁移到docker容器内,体验一下docker的应用。
安装docker
1 2 3 4
| yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io systemctl start docker
|
常用的几个命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # 查看本地镜像列表 docker images # 查看所有容器 docker ps -a # 拉取镜像 docker pull *** # 删除镜像 docker rmi *** # 运行容器 itd 分别为交互操作,终端, 后台运行 --name 指定运行的容器名称 -v 映射匿名卷 -p 映射端口 后两个参数是 镜像名称 和 运行容器后执行的命令 docker run -itd --name ** -v ** - p ** *** bash # 删除容器 docker rm -f ** # 进入正在运行的容器 -it 与 run中的意思相同 docker exec -it ** bash # 使用容易创建镜像 docker commit *** *** # 使用dockerfile构建镜像 docker build ***
|
在docker中部署程序体验
nginx
1 2 3 4 5 6 7 8
| # 先拉取镜像 docker pull nginx:latest # 运行容器 将nginx的配置文件映射到容器内对应目录, 映射外部需要访问的端口 docker run -itd --name nginx -v `pwd`/nginx/logs:/var/log/nginx -v `pwd`/nginx/conf.d:/etc/nginx/conf.d -v `pwd`/nginx/ssl:/etc/nginx/ssl -v `pwd`/nginx/html:/usr/share/nginx/html -p 80:80 -p 443:443 nginx bash # 可以进入容器内 进行交互 docker exec -it nginx bash
# 使用nginx访问不同的容器端口
|
tomcat
1 2
| docker pull tomcat docker run -itd --name tomcat -v `pwd`/tomcat/logs:/usr/local/tomcat/logs -v `pwd`/tomcat/webapps:/usr/local/tomcat/webapps -v `pwd`/tomcat/conf:/usr/local/tomcat/conf -p 8081:8081 tomcat bash
|
进浏览器访问
已经可以正常访问tomcat下webapps目录下部署的webNotepad页面了
dockerfile
dockerfile是构建镜像的配置文件,可以指定镜像的基础镜像,在构建的时候执行一些命令,指定镜像的匿名卷,暴露的端口等。主要就是各个指令的具体用法,随便一搜一大把,比如这个:点这里, 如果访问不了了,去搜一下就有了
dockerfile里面的run是在构建镜像的时候执行的命令,每一个命令都会包一层容器,所以最好将所有的命令组合到一条命令,例如:
1 2 3
| RUN echo "start" \ && npm install \ && echo "end"
|
docker-compose
这是一个运行多容器的一个工具,使用yml配置程序需要的所有服务(容器),通过docker-compose命令可以批量管理所有服务。
安装
1 2 3 4 5
| # 这个安装方法真粗暴 wget https://github.com/docker/compose/releases/download/1.26.0-rc3/docker-compose-Linux-x86_64 chmod +x docker-compose mv docker-compose /usr/local/bin ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
|
常用命令
1 2 3 4 5 6 7 8 9 10
| # 创建并运行所有的服务 -d 可选 代表后台运行 docker-compose up -d # 停止并删除所有的服务 docker-compose down # 运行所有/指定的服务 docker-compose start *** # 停止所有/指定的服务 docker-compose stop *** # 进入某一服务内部 docker-compose exec *** bash
|
docker-compose.yml
docker-compose的配置文件,可以配置各个容器服务的具体信息,结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| version: "3.7" services: nginx: image: nginx container_name: docker-nginx volumes: - "/root/docker/nginx/logs:/var/log/nginx" - "/root/docker/nginx/conf.d:/etc/nginx/conf.d" - "/root/docker/nginx/ssl:/etc/nginx/ssl" - "/var/data:/var/data" ports: - "80:80" - "443:443" environment: - "TZ=Asia/Shanghai" webapp: image: tomcat container_name: docker-webapp volumes: - "/root/docker/tomcat/logs:/usr/local/tomcat/logs" - "/root/docker/tomcat/ROOT:/usr/local/tomcat/webapps/ROOT" - "/root/docker/tomcat/conf:/usr/local/tomcat/conf" expose: - "8081" environment: - "TZ=Asia/Shanghai" hexo: build: ./hexo container_name: docker-hexo volumes: - "/root/docker/hexo/posts:/hexo/source/_posts" - "/root/docker/hexo/hblog-src/entrypoint.sh:/hexo/entrypoint.sh" - "/root/docker/hexo/hblog-src/posts:/hexo/posts" expose: - "4000" environment: - "TZ=Asia/Shanghai"
|
services 下为所有的容器,每日一个容器(nginx)下可以配置指导的镜像,容器名,匿名卷映射等,每个容器下个参数的意义基本与dockerfile的类似,可参考访问不了了,就随便搜一份
几个快捷指令
1 2 3 4 5
| # 批量删除所有已退出的容器 docker rm -f `docker ps -a | grep "Exited" | grep -v "grep" | awk '{print $NF}'` # 批量删除所有无标签的镜像 docker rmi -f `docker images | grep "<none>" | grep -v "grep" | awk '{print $3}'`
|
遇到的几个问题
webNotepad websocket无法连接
表现就是将webNotepad部署在tomcat容器中时,webNotepad可以访问,但是界面显示connect closed,在浏览器中F12 发现wss://*** 404了。
首先以为是nginx转发https的问题,于是把tomcat容器的暴露端口改为映射到宿主机,直接通过宿主机ip访问,依然出现ws://*** 404, 无果。
然后一番搜索,网上大部分解答都是 容器内的websocket监听的是本地地址,需要把localhost或者127.0.0.1 改成0.0.0.0 以便可以监听所有的地址。因为在容器没有netstat命令, 无法查看监听端口,且没有找到ServerEndPoint修改监听地址的地方,理论上应该是tomcat监听的哪就是哪,所以直接将tomcat运行到宿主机,通过netstat命令查看,发现已经是监听的0.0.0.0了,而且如果不是监听的0.0.0.0的话,就算部署在宿主机,在公网上也应该无法连接才对。
然后怀疑是docker的网络桥接会导致其中某一个握手过程不成功,于是将tomcat容器的网络 改成host,也就是直接使用宿主机网络,在宿主机中通过netstat命令可以看到,已经存在一个java进程在监听0.0.0.0:8081 了,就是我们的tomcat,结果用浏览器一连,依然是404。
排除了这些可能的因素以后,已经不知道直接部署在宿主机和部署在docker内有什么区别了,为了找更多的不同,分别的宿主机和docker内各运行了一次,然后截图tomcat的启动日志以及浏览器访问留下的日志。最后发现只有tomcat版本,以及java版本不同。tomcat 容器默认使用的是tomcat8 openjdk8,而宿主机是之前手动装的tomcat9 以及openjdk11。
虽然不知道是不是因为版本,但最后还是尝试了一次,不直接使用tomcat的镜像,写了一个dockerfile, form centos7.7 将手动下载的tomcat 解压到容器,然后安装jdk11, 再在容器跑tomcat的时候,websocket终于可以顺利连上了。
jenkins修改插件镜像源
在修改jenkins插件源时,因为国内源仅仅是复制了插件仓库,但是update.json里面的地址依然指向国外,所以在修改了update.json的所在地址之外,还需要将update.json中的国外地址通过host指向本地,然后通过nginx定向到想要的国内源。修改host的时候遇到了在build镜像的时候对hosts文件无访问权限。
尝试用USER 指令先将 用户换成 root, 修改完hosts之后再换回jenkins,但是依然出现了 sed: cannot rename /etc/sedR5SWIO: Device or resource busy
在网上搜索,发现是sed命令本质上是生成一个修改后的新文件,再替换原文件,但是在镜像构建过程中,这个文件是挂载进容器的,这样删除原文件,替换新文件就会出现上面的问题。但是echo命令就不需要删除原文件,于是将原来的 sed -i '$anginx mirrors.jenkins-ci.org' /etc/hosts
修改为 echo "$(sed '$anginx mirrors.jenkins-ci.org' /etc/hosts)" > /etc/hosts
然后发现自己傻了,这样根本行不通,每次docker启动的时候都会更新hosts文件,而往容器里增加域名解析,只需要在docker-compose.yml 中添加extra-hosts 就可以了。
普通用户使用docker
1 2 3 4 5 6 7 8
| # 查看是否有docker组 cat /etc/group
# 如果没有docker组 则添加 groupadd docker
# 将普通用户添加到docker组 usermod -G docker sictiy
|
将docker的基本目录从root目录,移动到sictiy的home目录后,需要修改docker的columns 映射到修改后的目录,每次都需要修改docker-compose.yml 太麻烦了,在.yml的同目录下添加.env文件,添加BASE_DIR=/home/sictiy/docker
, 并将docker-compose.yml 中所有目录修改为${BASE_DIR}***
最后的docker-compose.yml为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| version: "3.7" services: nginx: image: nginx container_name: docker-nginx volumes: - "${BASE_DIR}/nginx/logs:/var/log/nginx" - "${BASE_DIR}/nginx/conf.d:/etc/nginx/conf.d" - "${BASE_DIR}/nginx/ssl:/etc/nginx/ssl" - "/var/data:/var/data" ports: - "80:80" - "443:443" environment: - "TZ=Asia/Shanghai" jenkins: image: jenkins/jenkins container_name: docker-jenkins volumes: - "${BASE_DIR}/jenkins/logs:/var/log/jenkins" - "/home/jenkins:/var/jenkins_home" environment: - "TZ=Asia/Shanghai" extra_hosts: - "mirrors.jenkins-ci.org:172.17.0.1" webapp: build: ./tomcat container_name: docker-webapp volumes: - "${BASE_DIR}/tomcat/logs:/usr/local/tomcat/logs" - "${BASE_DIR}/tomcat/ROOT:/usr/local/tomcat/webapps/ROOT" - "${BASE_DIR}/tomcat/conf:/usr/local/tomcat/conf" expose: - "8081" environment: - "TZ=Asia/Shanghai"
... 后面还有类似的
|