赞
踩
如同博主大部分博客一样,文章都是会持续动态更新,可能各位看到这文章的时候,博主已经补充了好几个段落,所以话术排版风格有差异都是正常的。
linux安装docker 不声明linux版本的教程 都是耍流氓的教程
通过本文也会知道为什么那么多教程不一样
按F7 (不同主板可能有区别)进入advance mode 找到高级设置
按键盘 ↓ 键,选择CPU设置
继续按键盘 ↓ 键,找到VT 改成enabled
返回 ez mode ,保存并退出
其它主板位置可能有差异 但一般都是在CPU设置里面 找找是能看到的。
进入docker官网下载 如果没有注册 它要提示注册 先注册并验证一下邮箱
安装完成后 打开
(重要提醒:博主后来在win11环境中 下载last 版本 4.26.1 , 点击安装后 会直接开始安装 安装完成将自动重启,要是在服务器上操作 需要十分慎重!!!)
打开的时候可能会报错误(没报错则忽略) 下载一下环境 安装就好了
点击这里下载插件
如果没有安装linux虚拟机的话 docker还会有这样一个弹框 (没有报错请忽略 直接往下翻 找到第7步)
点进去这个网址,找到下图位置
根据里面的教程来安装 注意是使用powershell 输入命令 (windows10自带)
这里把我们需要操作的步骤都框起来了 很详细的教程有没有!
(我在写这些教程的时候是崩溃的, 博客还没写完 刚好遇到微软更新文档了)
注意是使用windows自带的powershell输入命令 ,会将linux下载到当前cd路径
Invoke-WebRequest -Uri https://aka.ms/wslubuntu2004 -OutFile Ubuntu.appx -UseBasicParsing
这里也是让我很头大的地方,微软上一版教程是举例Ubuntu16的, 结果我下载后 docker和linux内核一直有冲突问题,这个坑我替各位踩了 麻烦复制上面命令 上面这条命令就是下载Ubuntu20.04 。如果已经下载了Ubuntu16 或者其它的低版本,且启动docker时,很不幸出现了OCI runtime exec failed: exec failed: container_linux.go:345:getting the final child’s pid from pipe caused “EOF”": unknown 问题,卸载重安装一个Ubuntu20吧 升级内核的方法基本都是行不通的。
下载完成后 输入命令
# Ubuntu.appx 为下载的文件名称
Add-AppxPackage Ubuntu.appx
如果之前安装过Ubuntu16 先使用卸载命令:
# *Ubuntu16* 表示模糊搜索该名称的Appx包, |为连接符, remove-AppxPackage 表示移除
get-AppxPackage *Ubuntu16* | remove-AppxPackage
这里还有个很不幸的情况(没错 这个坑我也替大家踩了),就是如果已经安装了Ubuntu16,没有第一时间卸载,但是cd到另一个目录 又同时安装了20 , 这个时候会导致filezilla 只能连上Ubuntu16系统, 20是连接不上去的。 这个时候需要卸载Ubuntu16,20 ,并且重启windows,一定要重启 否则再安装Ubuntu20 会报错Add-AppxPackage : 部署失败,原因是 HRESULT: 0x80073CF6, 无法注册包。
首先 mvn package 把springboot打成jar包
可以在idea 右键new 一个Dockerfile 编写好后,和jar包一起复制到同个目录下
这里先给一个简单可用的例子 把内容复制进Dockerfile里面即可
# Docker image for springboot file run # VERSION 0.0.1 # Author: qkj # 基础镜像使用java FROM java:8 # 作者 MAINTAINER qkj <1005738053@qq.com> # 路径 # WORKDIR /app # VOLUME 指定了临时文件目录为/tmp。 # 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp VOLUME /tmp # 将jar包添加到容器中并更名为bootdemo ADD boot4dk.jar bootdemo # 运行jar包 RUN bash -c 'touch /bootdemo' ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/bootdemo"]
我这里把我的项目 boot4dk.jar 和Dockerfile 都复制进了 D:\dockerEvn 目录下
其中9090是docker对外端口 ,8080是springboot项目配置端口
docker run -p 9090:8080 -t boot4dk.jar
可以看到项目启动成功 注意jar包命名要用小写字母 不然会报错
docker images
可以看到我们的boot4dk已经在里面了
这句命令含义是 将 boot4dk.jar 导出至 d:\dockeros (注意这个路径也必须小写) 命名为bootdemo.tar ;
过程会有点慢 因为需要将java环境一起导出
docker save -o d:\dockeros\bootdemo.tar boot4dk.jar
一定要注意是 < 输错了会导入失败 且导致镜像被破坏
docker load <bootdemo.tar
还记得前面我们启动docker前安装了一个linux子系统嘛 它可以派上用场了 先在子系统捣鼓熟练了 再上自己linux服务器吧!
双击启动Ubuntu :
默认root是没有密码的,截图中的用户名 是我创建的用户
在自己账户下输入命令
sudo passwd root
它会提示输入自己账户密码进行验证 验证完毕后 设置root账户密码
接下来切换到root用户
su root
将自带的旧版本docker卸载
apt-get remove docker docker-engine docker.io containerd runc
注意 apt-get 是 Ubuntu的命令, 在centos上面 则使用 yum 命令
避坑点: 上面提过 Ubuntu16是会有linux环境问题的 (体现在启动镜像时),但因为网上的教程五花八门
所以这个也需要了解一下 :在Ubuntu16 中apt-get安装docker方式 : apt-get install docker.io
在Ubuntu20 中 ,apt-get install docker.io 会报错,提示没有这个资源:Package docker.io is not available, but is referred to by another package. 有的教程会推荐 先apt-get update ,再apt-get install docker.io ,但是这个安装是没有docker服务的 启动docker服务时会出现 docker: unrecognized service , 下面介绍Ubuntu20正确安装方式 会比较繁琐:
# 更新apt工具 sudo apt update # 安装必要的依赖软件,来添加一个新的 HTTPS 软件源 sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common # 使用下面的 curl 导入源仓库的 GPG key curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # 将 Docker APT 软件源添加到你的系统 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" # 安装docker 最新版 sudo apt install docker-ce docker-ce-cli containerd.io # 检查docker状态 service docker status 或 systemctl status docker # 启动docker服务 service docker start 或 systemct start docker
下载过程就是等待 等待过程发现有的时候它会假死在命令界面 时不时按几下enter键就好了
核心是配置root可以远程登录 我们通过filezilla软件登录root账户 将windows上面的镜像传输到linux上面
写到这里不得不提一句 不知道是下载的Ubuntu这一个版本配置是这样 还是所有Ubuntu配置都一个德行 默认是禁止密码登录的,centos则没有这种问题 导致filezilla一直登录失败 没想到是这原因 踩了个天坑。
输入命令:
vim /etc/ssh/sshd_config
按键盘 i 键进入编辑模式 将 PermitRootLogin prohibit-password 注释掉
改成
PermitRootLogin yes
含义是 root禁止密码登录 改成可以远程登录
此外 还需要将PasswordAuthentication和ChallengeResponseAuthentication都改为yes
PasswordAuthentication yes
ChallengeResponseAuthentication yes
重启ssh服务:
service ssh restart
或
systemctl restart ssh (或将ssh改成sshd 取决于不同的Linux版本 在centos7,8中是sshd)
这里可能会报错 sshd: no hostkeys available – exiting.
输入下面命令 并连续按下回车
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
当然 也可能在某些Ubuntu版本中 出现多个提示:
分别输入命令 按回车 回车 ,总之就是它提示缺少什么 我们就按照名字生成一下
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
这个时候再重启ssh就可以了
生成key之后 不要忘记了输入重启命令
service ssh restart
或 systemctl restart ssh (或sshd)
打开filezilla 测试是否能登录
把镜像复制进去linux虚拟机
这里我是在根目录建立了一个app文件夹 将镜像复制进app
复制完后 回到我们linux界面
cd /app
再次强调命令是 < 输错了镜像也坏了 只能重新传一份了 或者一开始就cp命令备份一份
docker load <bootdemo.tar
# 列出所有镜像
docker images
# 启动镜像
docker run imageName
示例如下图 (我的bootdemo.tar 镜像名字为boot4dk.jar , 当然说它是仓库,不是镜像名也对 能懂就行 不咬文嚼字)
我们上面的举例是远程打包好了镜像 再进行导入的 那么如果想直接在linux上面部署项目至docker应该怎么做呢? 和windows教程类似:
# 最后面有个 . 表示dockerfile在当前目录
docker build -t boot4dk.jar .
# build完之后 再run就好了 9090是docker对外端口 8080是项目端口
docker run -p 9090:8080 -t boot4dk.jar
(run 的时候可能会提示要登陆 没有账号的话 去它报错信息中给出提示的网站是注册一下就好了)
systemctl 一般在centos高版本中使用 service 一般在centos低版本 或者 Ubuntu中使用
# docker 查看状态
systemctl status docker 或 service docker status
# 启动docker
systemct start docker 或 service docker start
# 重启 docker
systemct restart docker 或 service docker restart
# 停止 docker
systemct stop docker 或 service docker stop
# docker构建 注意后面有个 . 表示dockerfile在当前路径
docker build -t xxx.jar .
# docker 后台启动 并输出日志 其中9090是docker端口 8080是项目端口 xxx是jar包名 2>&1 表示错误 重定向标准输出
docker run -d -p 9090:8080 -t xxx.jar >output 2>&1
# docker 停止服务 如果停止不了 就用下面的移除命令吧 containerId也可以是container name
docker stop containerId
# 停止某个容器运行 docker stop container_id_or_name # 移除某个容器 docker rm containerId # 删除所有停止运行的容器: docker container prune # 移除所有容器, $() 可以替换为反引号 `` docker rm $(docker container ls -aq) # 移除某个镜像下的容器 grew -w :精确查找,awk '{print $1}' awk语法 显示第一列(ID列) docker rm -f `docker container ls -a|grep -w ImageName|awk '{print $1}'` # 移除某个端口的容器 docker rm -f `docker container ls -a|grep -w yourPort|awk '{print $1}'` # 列出所有容器(运行中) docker container ls 或 docker ps # 列出所有容器 (包括非运行) docker container ls -a # 列出所有容器的id (包含非运行) docker container ls -aq # 列出所有镜像 docker images # 移除某个镜像 imageId或name都可以 docker rmi imageId # 移除所有镜像 docker rmi $(docker images -aq) # 删除所有未被 tag 标记和未被容器使用的镜像: docker image prune # 删除所有未被容器使用的镜像: docker image prune -a
tips: 如果更新了服务 需要重新运行镜像 完整步骤为:
停止当前容器
移除当前容器
移除当前镜像
重新载入镜像
启动镜像
docker images完整的语法为 : docker images [OPTIONS] [REPOSITORY[:TAG]]
举个栗子 :docker images --digests boot4dk.jar:latest
类似的栗子: docker images -a 自己根据需要对命令进行组合
举一反三时间:现在知道日常工作中 敲其它命令 提示options时 该怎么写了吧?
OPTIONS说明:
-a :列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);
–digests :显示镜像的摘要信息;
-f :显示满足条件的镜像;
–format :指定返回值的模板文件;
–no-trunc :显示完整的镜像信息;
-q :只显示镜像ID。
地址: https://docs.docker.com/engine/install/centos/
(这是一个年年整活的博主,年年遇bug。 这回挑战的是python写的web项目,Django是python的一个web框架。)
java web项目可以打成jar包 复制到docker中通过jdk运行,所以dockerfile核心就是1.复制 2.启动
python和java不一样 跨平台并不是那么优势 博主是参照 gitee django-vue-admin开源项目进行部署的,理论上来说 pyhton项目就是把代码搬去虚拟环境 重新下载requirement里的依赖 并启动。
(为什么使用docker 而不是python的virtualenv虚拟环境呢?因为博主亲测 同一个镜像源地址 同一python版本 在windows以及docker中依赖都是下载成功的,但是在linux下载失败 期间经历了大量尝试都于事无补 ,这一刻java跨平台的优势体现的淋漓尽致 )
该python web项目是使用的docker-compose打包的:
docker-compose.yml配置
version: "3" services: # dvadmin-web: # container_name: dvadmin-web # ports: # - "8080:8080" # build: # context: ./ # dockerfile: ./docker_env/web/Dockerfile # environment: # TZ: Asia/Shanghai # volumes: # - ./docker_env/nginx/my.conf:/etc/nginx/conf.d/my.conf # expose: # - "8080" # networks: # network: # ipv4_address: 177.8.0.11 dvadmin-django: build: context: . dockerfile: ./docker_env/django/Dockerfile container_name: dvadmin-django working_dir: /backend # 打开mysql 时,打开此选项 depends_on: - dvadmin-mysql # 打开mysql end===== environment: PYTHONUNBUFFERED: 1 DATABASE_HOST: dvadmin-mysql TZ: Asia/Shanghai volumes: - ./backend:/backend - ./logs/log:/var/log ports: - "8000:8000" expose: - "8000" restart: always networks: network: ipv4_address: 177.8.0.11 # 打开mysql时的配置: dvadmin-mysql: image: mysql:8.0 # 这里指向远端mysql地址 因为我不想mysql在虚拟环境中 extra_hosts: - "dvadmin-mysql:8.134.10.1" container_name: dvadmin-mysql #使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限 #设置为true,不然数据卷可能挂载不了,启动不起 privileged: true restart: always ports: - "3308:3306" environment: MYSQL_ROOT_PASSWORD: "yourPassword" MYSQL_DATABASE: "django-vue-admin" TZ: Asia/Shanghai command: --wait_timeout=31536000 --interactive_timeout=31536000 --max_connections=1000 --default-authentication-plugin=mysql_native_password volumes: - "./docker_env/mysql/data:/var/lib/mysql" - "./docker_env/mysql/conf.d:/etc/mysql/conf.d" - "./docker_env/mysql/logs:/logs" networks: network: ipv4_address: 177.8.0.11 # 如果使用celery 插件,请自行打开此注释 # dvadmin-celery: # build: # context: . # dockerfile: ./docker_env/celery/Dockerfile # # image: django:2.2 # container_name: dvadmin-celery # working_dir: /backend # depends_on: # - dvadmin-mysql # environment: # PYTHONUNBUFFERED: 1 # DATABASE_HOST: dvadmin-mysql # TZ: Asia/Shanghai # volumes: # - ./backend:/backend # - ./logs/log:/var/log # restart: always # networks: # network: # ipv4_address: 177.8.0.14 # dvadmin-redis: # image: redis:6.2.6-alpine # 指定服务镜像,最好是与之前下载的redis配置文件保持一致 # container_name: dvadmin-redis # 容器名称 # restart: on-failure # 重启方式 # environment: # - TZ=Asia/Shanghai # 设置时区 # volumes: # 配置数据卷 # - ./docker_env/redis/data:/data # - ./docker_env/redis/redis.conf:/etc/redis/redis.conf # ports: # 映射端口 # - "6379:6379" # sysctls: # 设置容器中的内核参数 # - net.core.somaxconn=1024 # command: /bin/sh -c "echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf && redis-server /etc/redis/redis.conf --appendonly yes" # 指定配置文件并开启持久化 # privileged: true # 使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限 # networks: # network: # ipv4_address: 177.8.0.15 networks: network: ipam: driver: default config: - subnet: '177.8.0.0/16'
Dockerfile:
FROM registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/python38-base-backend:latest
WORKDIR /backend
COPY ./backend/ .
RUN awk 'BEGIN { cmd="cp -i ./conf/env.example.py ./conf/env.py "; print "n" |cmd; }'
RUN python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ -r requirements.txt
CMD ["/backend/docker_start.sh"]
目录层级:
docker启动命令:
docker-compose up -d --build
(或通过docker desktop启动 注意不要同时启动导致端口占用了,使用命令提示端口占用时 可以先去desktop里面检查)
踩坑点一:
docker-compose.yml里面配置了networks , networks这边可能会导致端口被占用的报错:
Error response from daemon: Address already in use
(前提是netstat -ano | findstr port 排查了自己windows本地确实没有端口占用)
有对docker了解的同学 欢迎在评论区用通俗易懂的语言 补充这个networks的用途,
博主暂时不知道到底可以干嘛 于是注释掉了
注释后docker会用默认的network
# networks:
# network:
# ipv4_address: 177.8.0.11
踩坑点二:
请把梯子关掉,否则可能导致接下来导出的镜像有问题
表现形式为:
导出:
docker save 008ce47da0c6 >meituan.tar
(008ce47da0c6 为镜像id, meituan.tar 为导出名字 , 导出至当前目录)
导入镜像
(如果提示archive/ tar : invalid tar header 请参考上面的踩坑点)
docker load <meituan.tar
查看镜像列表
docker images
运行镜像 (008ce47da0c6 为镜像id 8000为端口 前者为docker映射端口 后者为项目端口)
docker run -d -p 8000:8000 -t 008ce47da0c6 >output 2>&1
通过本文的两个项目部署,我们也可以大致学习Dockerfile命令的含义:
springboot项目Dockerfile:
# Docker image for springboot file run # VERSION 0.0.1 # Author: qkj # 基础镜像使用java 其实就是声明运行环境 FROM java:8 # 作者 MAINTAINER qkj <1005738053@qq.com> # 路径 可以当做cd命令来理解 WORKDIR /var/lib/jenkins/workspace/springboot # VOLUME 指定了临时文件目录为/tmp。 # 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp VOLUME /tmp # 将jar包添加到容器中并更名为springboot.jar ADD springboot-core-1.0.0.jar /springboot.jar # 运行jar包 RUN bash -c 'touch /springboot.jar' ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/springboot.jar"]
Django Dockerfile
FROM registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/python38-base-backend:latest
# 路径 可以当做cd命令来理解
WORKDIR /backend
# 可以理解为将当前目录下的backend文件夹 复制到docker中 后面这个. 是镜像路径
COPY ./backend/ .
RUN awk 'BEGIN { cmd="cp -i ./conf/env.example.py ./conf/env.py "; print "n" |cmd; }'
RUN python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ -r requirements.txt
CMD ["/backend/docker_start.sh"]
教程到此结束了 本篇博客过程中列出了很多bug 踩坑点 多注意一下
踩的坑多了 路也就平了
(平不了 走的路越多 坑只会越踩越深)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。