文章目录
Docker 基础命令指南
本文详细介绍了docker中常用的命令,并且通过实际的例子介绍了如何使用docker compose, docker swarm部署多副本应用。
帮助命令
帮助文档地址:Docker官方参考文档
Docker的帮助命令可以用来获取不同命令的详细信息。
docker version # 查看Docker版本
docker info # 获取Docker系统信息
docker 命令 --help # 获取特定Docker命令的帮助信息
帮助命令
docker version
docker info
docker 命令 --help #帮助命令
镜像命令
查看镜像
列出本地存储的所有镜像。
sudo docker images
搜索镜像
在Docker Hub中搜索镜像。
sudo docker search nginx
下载镜像
从Docker Hub拉取镜像。
sudo docker pull [镜像名称]:[tag]
# 拉取openjdk 11
sudo docker pull openjdk:11-jre
# 拉取nginx latest
sudo docker pull nginx
删除镜像
删除指定的本地镜像。
# 不加-f的话,如果有container用了这个image,那就会报错删不掉这个
# 或者可以手动先把相应的container删除
sudo docker rmi -f [镜像名字或者id或者id的前几个字母]
基于Dockerfile构建镜像
根据Dockerfile创建新镜像。
# 假设Dockerfile在当前目录
docker build -t [镜像名称]:[tag] [Dockerfile所在目录]
# 比如镜像名称是myapp-1.0-SNAPSHOT.jar,设置tag为1.0
# dockerfile里面需要的文件也要在当前目录下,比如jar包
docker build -t myapp-1.0-SNAPSHOT.jar .
容器命令
创建并启动容器
使用docker run
命令来创建并启动一个容器。
sudo docker run [可选参数] image
# 参数说明
--name="Name" # 容器命名
-d # 以后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # 指定容器的端口 -p 8080:8080
# -p 主机端口:容器端口
# -p ip:主机端口:容器端口
-P # (大写P)随机指定端口
列出容器
显示当前正在运行的容器信息。
sudo docker ps
# 参数说明
-a # 列出当前运行的及历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器编号
退出容器
退出当前容器的方法。
exit # 停止并退出
ctrl + P + Q # 容器不停止退出
删除容器
删除指定的容器。
docker rm [容器名字或者id或者id的前几个字母]
启动和停止容器
对容器进行启动、重启、停止和强制停止操作。
docker start # 启动容器
docker restart # 重启容器
docker stop # 停止容器
docker kill # 强制停止容器
容器网络相关
创建网络
创建Docker网络。
docker network create mynet
连接容器到网络
将指定容器连接到网络。
docker network connect mynet [containerId]
查看网络详情
查看网络详情,包括连接到网络的容器。
docker inspect mynet
查看所有网络
列出所有Docker网络。
docker network ls
Docker其他常用命令
后台启动容器
在后台运行容器,需要确保有一个前台进程。
docker run -d 镜像名
查看日志
查看容器日志。
docker logs 容器id
查看容器内进程
查看容器内部的进程信息
docker top 容器id
查看镜像元数据
dokcer inspect 容器id
进入运行中的容器
进入当前正在运行的容器。
# 方法一:进入容器后开启新窗口
docker exec -it 容器id bashshell
# 方法二:进入正在执行的容器窗口,不启动新进程
docker attach 容器id
从容器内拷贝文件
将容器内的文件拷贝到主机上。
docker cp container_id:/path/to/file /path/to/host/file
Dockerfile相关
Dockerfile主要是用来构建docker镜像的。
Dockerfile结构解读
- 文件名:Dockerfile
- 保留字命令必须全大写
- 每行只能有一条指令
#
表示注释- 指令从上到下执行
- 每条指令都会创建一个新的镜像层,所以指令少一点比较好,省空间
基于Dockerfile构建镜像
保留命令
# 当前镜像是基于哪个镜像的,第一个指令必须是FROM,比如下面就是以最新的
FROM alpine:3.15
# 镜像维护者的姓名和邮箱地址(废弃了)
MAINTAINER
# 可以使用shell语法
RUN yum install -y vim
# 也可以使用下面这种
RUN ["yum", "install", "-y", "vim"]
# 当前容器对外暴露的端口号(只是声明,给别人看的,没有实际的影响,可以写在除了第一行以外的任何一行)
EXPOSE 8080
# 指定在创建容器后,终端默认登录进来的容器内的工作目录, 这个命令之后的操作都是在这个目录里面进行
# 如果不存在这个目录,会自动创建,可以绝对路径,也可以相对路径,默认是在根目录
WORKDIR /apps
# 比如,设置一个变量BASE_PATH, 然后用这个 变量的时候需要用$符号
ENV BASE_PATH=/apps/data
WORKDIR $BASE_PATH
# 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL
# 比如把dockerfile所在文件目录的aa.txt文件拷贝到容器内/apps/data目录
ADD ./aa.txt /apps/data
# 也可以直接用容器内的当前目录
ADD ./aa.txt ./data
# 如果是url,会自动下载文件,拷贝到容器里面
ADD https://download.apache.org/tomcat/tomcat-9/v9.0.48/bin/apache-tomcat-9.0.48.tar.gz ./data
# 拷贝文件和目录到镜像中,跟add类似,但只能从文件上下文拷贝文件,不能通过url
# 比如下面的命令就是把宿主机上当前Dockerfile所在目录下的my-app-1.0-SNAPSHOT.jar复制到容器内工作目录,并重命名为app.jar
COPY my-app-1.0-SNAPSHOT.jar app.jar
# 容器数据卷,用于数据保存和持久化工作(仅仅是一个声明,告诉使用者可以挂在这个目录到宿主机中), 比如声明容器内当前工作目录的data文件夹为挂载点
VOLUME ./data
# 指定一个容器启动时要运行的命令, dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
CMD
# 指定一个容器启动时要运行的命令, ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及其参数
# CMD和ENTRYPOINT的语法,都是可以使用shell命令或者字符串数组的形式,推荐后者
ENTRYPOINT
# CMD和ENTRYPOINT区别是什么?
# CMD: docker run 镜像:版本号 覆盖自己定义的命令
# ENTRYPOINT: docker run --entrypoint=覆盖指令 镜像:版本号 传递参数
# 假设dockerfile有以下两行内容
FROM ubuntu
CMD ["echo", "Hello World"]
# 如果运行`docker run -it myImage`, 会输出"Hello World"
# 但如果运行`docker run -it myImage /bin/bash`, 就会进入 bash,并且 CMD 指定的命令不会被执行。
# 假设dockerfile有以下两行内容
FROM ubuntu
ENTRYPOINT ["echo"]
# 如果运行`docker run -it myImage`, 不会输出任何内容, 因为没有给echo指定参数
# 如果运行`docker run -it myImage "Hello World"`, 它会输出 "Hello World",因为 "Hello World" 被作为参数传递给了 ENTRYPOINT。
# 所以一般这两个命令配合起来使用,以便于更换命令之后的参数,而不覆盖命令本身,比如
ENTRYPOINT ["java", "-jar"]
CMD ["/apps/data/nblog.jar"]
Dockerfile构建镜像
注意,Dockerfile所在的目录的文件都会被发送到docker engine,
所以最好弄个新文件夹,或者同级目录不要有无关的文件,
以减少构建上下文的大小,提高镜像构建的效率。
# 根据当前目录下的Dockerfile文件,构建出mycentos镜像,标签为latest
# 注意后面有个英文句号,代表当前目录
docker build -t mycentos:latest .
Dockerfile构建镜像实战
下面来通过几个例子来巩固上面的知识
构建jdk21镜像
为了能够部署基于jdk21的java项目,我们需要一个装有jdk21的linux镜像作为基础镜像,下面开始构建。
- 编写Dockerfile
# 首先创建一个空目录方便后续操作
mkdir $HOME/docker-tmp
cd $HOME/docker-tmp
# 创建Dockerfile文件
touch Dockerfile
vim Dockerfile
将下面内容写入Dockerfile:
# alpine是一个轻量化的linux镜像
FROM alpine:3.15
ARG version=21.0.0.34.1
# Please note that the THIRD-PARTY-LICENSE could be out of date if the base image has been updated recently.
# The Corretto team will update this file but you may see a few days' delay.
RUN wget -O /THIRD-PARTY-LICENSES-20200824.tar.gz https://corretto.aws/downloads/resources/licenses/alpine/THIRD-PARTY-LICENSES-20200824.tar.gz && \
echo "82f3e50e71b2aee21321b2b33de372feed5befad6ef2196ddec92311bc09becb /THIRD-PARTY-LICENSES-20200824.tar.gz" | sha256sum -c - && \
tar x -ovzf THIRD-PARTY-LICENSES-20200824.tar.gz && \
rm -rf THIRD-PARTY-LICENSES-20200824.tar.gz && \
wget -O /etc/apk/keys/amazoncorretto.rsa.pub https://apk.corretto.aws/amazoncorretto.rsa.pub && \
SHA_SUM="6cfdf08be09f32ca298e2d5bd4a359ee2b275765c09b56d514624bf831eafb91" && \
echo "${SHA_SUM} /etc/apk/keys/amazoncorretto.rsa.pub" | sha256sum -c - && \
echo "https://apk.corretto.aws" >> /etc/apk/repositories && \
apk add --no-cache amazon-corretto-21=$version-r0 && \
rm -rf /usr/lib/jvm/java-21-amazon-corretto/lib/src.zip
ENV LANG C.UTF-8
ENV JAVA_HOME=/usr/lib/jvm/default-jvm
ENV PATH=$PATH:/usr/lib/jvm/default-jvm/bin
- 构建镜像
假设将镜像命名为21-jdk-alpine
docker build -t 21-jdk-alpine .
- 查看镜像
docker images
可以看到名为21-jdk-alpine:latest
的镜像已经构建好了
- 推送镜像到docker hub(可选)
如果想要把镜像推送到docker hub公共仓库或者私有仓库,方便自己后续使用的话,可以按下面步骤操作:
参考官方文档 hub.docker.io
# 先登录docker
docker login --username=myuname
# 输入密码之后,可以看到Login Succeeded,说明登录成功了,然后推送image
docker push 21-jdk-alpine:latest
Docker compose相关
首先关于docker compose和docker-compose这两个命令,docker compose
是V2版,目前和以后使用的命令,docker-compose
是V1版,会逐渐废弃,所以后续都使用docker-compose
。
docker compose安装
docker compose在windows和macos上是随docker一起安装的,但在linux上没有,所以linux上需要单独安装docker compose。
docker compose的安装就是把一个sh文件下下来放到指定的位置就行(/usr/local/bin/docker-compose)
安装方式,在线安装:
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m`" > /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
启动服务
必须在docker-compose.yml的目录执行。
可以针对项目或者项目的某个service, 如果没有指定,则默认时针对整个项目。
不管服务有没有创建过,都重新构建并重启服务
# 服务不存在则构建并启动,服务已存在则直接重启(已有镜像的话不会重新构建)
docker compose up
# 参数解释
-f # 指定docker-compose.yml文件名,默认会找docker-compose.yml
-d # 后台启动
--build # 构建服务
# 例子: 根据当前目录下的docker-compose.yml文件构建myservice
docker compose build myservice
# 例子: 根据当前目录下的docker-compose.yml文件重新构建(文件中设定了build的)并重启文件里的所有服务,后台启动
docker compose up --build -d
# 例子:在上面的基础上,指定文件里的名为myservice的服务
docker compose up --build -d myservice
启动已经创建过的服务
docker compose start
进入某个服务内部
docker compose exec 服务id bash
列出所有运行的服务
docker compose ps
查看compose所有服务的日志
docker compose logs -f
暂停/停止/删除服务
# 暂停服务
docker-componse pause
# 恢复服务
docker-compose unpause
# 停止服务
docker compose stop
# 删除服务(会关闭里面的所有容器, 并删除网络)
docker compose down
# 删除指定服务
docker compose rm myservice
# 选项说明
-f # 强制删除,即使有运行中的container
-v # 删除相关的数据卷
# 重启相关,比如重启名为myservice的服务
# 重启所有开启中的服务
docker compose restrat
# 重启指定服务
docker compose restart myservice
# 10秒后重启指定服务
docker compose -t 10 restart myservice
Docker swarm相关
docker swarm是docker自带的容器编排管理工具,对于比较小型的应用,使用docker swarm多副本部署项目完全足够了。
简单介绍一下docker swarm的优点:
- 一个服务可以开多个副本,这些副本全部共用一个端口,docker swarm自动对容器内的副本进行负载均衡
- 简单易用:Docker Swarm内置于Docker Engine中,无需安装额外的组件,使用起来相对简单。
- 高可用性:Docker Swarm支持高可用部署,可以容忍节点故障,保证服务的高可靠性。
- 横向扩展:Docker Swarm支持服务的横向扩展,可以根据需求动态增加或减少服务实例。
初始化docker swarm
首先之前如果没有使用过docker swarm,需要初始化一下docker swarm
# 初始化docker swarm
docker swarm init
# 或者指定当前节点的ip,方便其他的节点加入
docker swarm init --advertise-addr 192.168.31.12
init完成之后,会有如下提示,可以把key记下来,方便以后其他节点join进来
Swarm initialized: current node (7ko7fomyjbvztcrnx5ndzhlv2) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-013ti9s1yywzuqn7j4z534f26vee83ljx1z4oe4t11vo8koyh2-2yfn82ze8g7enm8pfku0r5l20 192.168.31.12:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
启动/重启/删除服务,日志查看
下面的clientapp
是自定义的stack name
, 后面需要用到
# 根据当前目录下的docker-compose.yml启动名为myapp的stack
docker stack deploy -c docker-compose.yml myapp
# 查看现有的stack
docker stack ls
# 查看服务的状态
docker service ls
# 查看stack里所有service的状态
docker stack ps myapp
# 查看myapp_service01的状态
docker service ps myapp_service01
# 查看日志
# 目前不支持直接看整个stack的日志,只能单独看docker-compose.yml里面每个service的日志
# 比如docker-compose.yml有个名为service01的服务,则需要用下划线拼接stack和service,如下所示:
docker services logs -f myapp_service01
# 选项说明
--follow # 实时查看日志
--tail [n] # 只看尾部n行的日志
# 删除名为myapp的stack
docker stack rm myapp
# 强制使用image重启服务
# 下面指令意思是使用service01-image:latest镜像重启myapp这个stack里面的service01服务
docker service update --force --image service01-image:latest myapp_service01
docker swarm实战:发版服务
实操任务描述:现在有个java springboot项目,已经通过maven打包好了名为myapp-1.0-SNAPSHOT.jar
的jar包,需要部署到云服务上
- 登录云服务器(或者本地搞个虚拟机)
- 假定工作目录为
/root/docker-deploy
,将myapp-1.0-SNAPSHOT.jar
传输到该目录 - 在该目录创建Dockfile文件,写入如下内容:
FROM openjdk:21-jdk-alpine
ENV TZ=Asia/Shanghai \
APP_PATH=/data \
JAVA_OPTS="-Xms256m -Xmx256m"
WORKDIR $APP_PATH
COPY myapp-1.0-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -jar app.jar" ]
- 构建镜像
docker build -t myapp-image .
- 创建docker-compose.yml文件,写入如下内容
version: "3.8"
services:
service01:
image: myapp-image:latest # 确保构建好您的镜像,并替换此处
ports:
- "8080:8080" # Swarm 将自动负载均衡到所有副本
extra_hosts:
- "host.docker.internal:host-gateway" # 设定宿主机host地址,方便容器内服务通过http://host.docker.internal:[端口号]访问宿主机的服务
deploy:
replicas: 3 # 设置您需要的副本数量
update_config:
parallelism: 1 # 每次更新一个副本
delay: 30s # 更新之间的延迟
order: start-first # 首先启动新容器,然后停止旧容器
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
networks:
- mynet
volumes:
- myapplog:/data/logs # 使用单个卷,或根据需要调整
environment:
- "SPRING_PROFILES_ACTIVE=prod"
volumes:
myapplog:
networks:
mynet:
- 部署启动服务
docker stack deploy -c docker-compose.yml myapp
- 查看服务启动状况
这里需要等一会儿,看到replicas 3/3说明所有副本都启动成功
# 查看stack是否创建成功
docker stack ls
# 查看服务状态
docker service ls
# 查看服务日志
docker service logs -f myapp_service01
# 或者可以直接看volume里面的挂载的日志文件
# 1.先找到volume在宿主机实际的存储地址,注意这个volume是要加上stack的名称的
# 可以用docker volume ls看看有哪些存储卷
docker volume inspect myapp_myapplog
# 找到Mountpoint,然后进入目录找到对应的日志文件即可
cd /var/lib/docker/volumes/myapp_myapplog/_data
docker swarm实战:不停机更新服务
下面介绍一下如何不停机更新发版。
在上面的docker-compose.yml的deploy中,我们已经配置了重启的策略,就是重启的时候先启动新的容器,再停掉旧的容器,这样就可以实现用户无感知,不停机更新发版
- 把更新后的代码打包好,把jar包传输到
/root/docker-deploy
- 构建镜像
cd /root/docker-deploy
docker build -t myapp-image .
- 强制使用新的image重启服务
docker service update --force --image myapp-image:latest myapp_service01
- 查看启动日志
docker service logs -f myapp_service01
docker 仓库相关
修改镜像的tag
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
登录远程仓库
# 登录远程镜像仓库(后面不加host就是默认登录docker hub)
docker login --username=[你的docker hub账号名称]
# 或者登录指定的仓库,比如阿里云镜像
docker login --username=myaliname registry.cn-hangzhou.aliyuncs.com
从指定远程仓库拉取镜像
# 假设从阿里云私有镜像拉取
docker pull registry.cn-hangzhou.aliyuncs.com/myrepo/myapp:1.0.0
推送本地镜像到远程仓库
# 先登录远程镜像仓库
docker login --username=myaliname registry.cn-hangzhou.aliyuncs.com
# 修改镜像tag,设定镜像地址
docker tag [需要推送的镜像id] [仓库地址]:[镜像版本号]
# 比如:
docker tag 99dcb1016b23 registry.cn-hangzhou.aliyuncs.com/myrepo/myapp:1.0.0
# 推送镜像到远程镜像仓库
docker push registry.cn-hangzhou.aliyuncs.com/myrepo/myapp:1.0.0