docker 基础命令
启动、重启容器
# docker start 容器id
$ docker start 345678765
# 后台启动 docker run -d 镜像名
$ docker run -d centos #启动后就停止,因为没有前台运行程序,docker把它停掉了
# 启动并进入容器
# docker run -it 容器名称 /bin/bash
$ docker run -it centos /bin/bash
# 重启容器 docker restart 容器id
$ docker restart 345678765
退出容器
# 退出容器
# exit #回停止容器的运行
# 使用 Ctrl+ p +q 不停止容器退出
ning@DESKTOP-1BQCBJ0:~$ docker run -it centos
[root@52a938078f80 /]# ning@DESKTOP-1BQCBJ0:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
52a938078f80 centos "/bin/bash" 12 seconds ago Up 10 seconds
停止容器
$ docker stop 容器id # 停止当前正在运行的容器
$ docker kill 容器id # 强制停止当前正在运行的容器
查看容器的进程信息 和 容器
# 命令 docker top 容器id
$ docker top 0668b6e0960f
UID PID PPID C STIME
999 2120 2100 0 07:23
# 查看正在运行的容器
$ docker ps
# 查看所有容器,包括历史运行的容器
$ docker ps -a
# 查看所有容器的id
$ docker ps -aq
删除镜像
$ docker rmi 镜像id
删除容器
$ docker rm 容器id #删除指定的容器,不能删除正在运行的容器
$ docker rm -f 容器id # 删除容器
$ docker rm -f $(docker ps -aq) #删除所有的容器
日志
# 查看所有日志 docker logs -tf 容器id
$ docker logs -tf 0668b6e0960f
# 查看多少条数据 docker logs -tf --tail 条数 容器id
docker logs -tf --tail 1 0668b6e0960f
查看容器的元数据和信息
# 查看容器的元数据和信息 docker inspect 容器id
$ docker inspect 0668b6e0960f
进入容器中
# ①进入容器中
# 命令 docker exec -it 容器id /bin/bash
ning@DESKTOP-1BQCBJ0:~$ docker exec -it 0668b6e0960f /bin/bash
root@0668b6e0960f:/#
# ②进入容器
# 命令 docker attach 容器id
$ docker attach 0668b6e0960f
# 区别:
# docker exec 进入容器中,会打开一个新的终端,可以操作
# docker attach 进入容器中正在执行的终端,不会启动新的进程
文件拷贝从容器内拷贝到主机
#创建文件 touch 文件名.类型
$ touch ning.java
# docker cp 容器id:文件绝对路径 要拷贝到的位置
$ docker cp df81fd7552f2:/home/ning.java /home
# 拷贝文件夹下所有内容,递归操作
$ cp -r webapps.dist/* webapps #拷贝webapps下dist目录中所有文件到webapps中
提交镜像
docker commit -m="作者" 容器id 目标镜像名称:[tag]
# 然后docker images就可以看到自己提交的镜像
# 因为docker提供的镜像比较精简小巧,删除了大部分的东西,只保留基础的东西,例如tomcat的webapps下面是空的没# 有应用,这时候自己可以拷贝一份过来,然后提交镜像,之后再使用tomcat就可以使用自己提交的镜像。
容器数据卷
容器数据同步到本地。容器内数据的存储位置映射到本地路径来达到数据安全的目的,保证容器删除数据不丢失;
总的来说就是容器的持久化和同步操作。容器间可以数据共享,这样可以多个容器绑定到一个目录,方便查看管理;
-
使用命令双向绑定目录 -v
# 主机home目录下的test文件夹映射容器内的home文件夹,不论哪边变化都会同步,如果停止容器, # 在主机文件夹下修改,容器内的文件同样会被同步修改;使用-v,和使用-p类似 # docker run -it -v 主机目录:容器内的目录 容器名称 $ docker run -it -v /home/test:/home centos
不止是同步数据方便,修改容器的配置文件同样,将路径映射,只需要在主机进行配置文件的修改,容器中的配置文件自动同步,不需要每次修改配置文件都进入容器中;
这样的操作存储空间的占用是双倍的;
容器中的目录或者文件删除了,主机的文件或目录不会被删除;
多个挂载的话可以使用多个
-v
-
匿名挂载和具名挂载
匿名就是不指定挂载卷的名称,默认是一串数字+字母
# -d 后台运行 -P大写的P随机端口 --name指定容器名称 -v数据卷挂载,随机名称和创建容器一致主机路径 docker run -d -P --name nginx01 -v /ect/nginx nginx
具名挂载就是不指定主机路径,指定挂载卷名称
# 挂载卷名为ning,使用 docker volume ls 查看数据卷可以看到 docker run -d -P --name nginx02 -v ning:/ect/nginx nginx
docker file
命令:
# FROM 指定那种镜像作为创作镜像的基础镜像
# MAINTAINER 指明该镜像的作者和其电子邮件
# RUN 在新镜像内部执行的命令,可以使用\来换行
# COPY 将主机的文件复制到镜像内,如果目的位置不存在,Docker会自动创建所有需要的目录结构
# 注意:需要复制的目录一定要放在Dockerfile文件的同级目录下
# ADD 将主机的文件复制到镜像中,往镜像中添加内容
# EXPOSE 暴露端口为主机做映射
# WORKDIR 镜像的工作目录
# ONBUILD 当一个包含ONBUILD命令的镜像被用作其他镜像的基础镜像时,执行该命令
# VOLUME 挂载目录,数据卷挂载
# CMD 指定容器启动时候运行的命令,只有最后一个生效,命令会被最后一个替代
# ENTRYPOINT 指定容器启动时候运行的命令,不会被覆盖,命令会被追加
# ENV 构建的时候设置环境变量
-
制作一个centos
# 1.编写dockerfile文件 FROM centos MAINTAINER ning<113202377@qq.com> EVN MYPATH /usr/local WORKDID $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPORE 80 CMD /bin/bash # 2.通过文件构建镜像 docker build -f dockerfile文件路径 -t 创建的镜像名:版本 . $ docker build -f ning_centos -t my_centos:1.0 . # 3.测试运行 运行原来没有的添加上的命令 $ docker run -it my_centos:1.0
查看镜像的制作过程
# 查看镜像的制作过程 docker history 镜像id $ docker history 8d7e85ea90a9
-
制作Tomcat
FROM centos MAINTAINER ning<1132023770@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8ull-linux-x64.tar.gz /usr/local ADD apache-tomcat-9.0.22.tar.gz /usr/local RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_11 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out
build成功之后,数据卷挂载,双向绑定一下,方便项目的发布和日志文件等等的操作。
-
推送镜像到dockerhub
# 推送镜像到dockerhub # 1.登录到dockerhub docker login -u 用户名 # 2.推送镜像 docker push 用户名/镜像名称+版本号
springboot 微服务打包docker镜像
-
创建springboot项目,写入测试代码打包
-
创建
Dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]
-
上传文件到服务器
-
切换到文件夹位置,执行
Dockerfile
文件,生成镜像docker build -t springboot-webserver .
-
运行镜像
docker 容器互连
查看网路模式
ning@DESKTOP-1BQCBJ0:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
1fdad9d9dd06 bridge bridge local
0770dfdc1c7c host host local
c7cc8e75dd17 none null local
容器互连
由于使用ip地址的话每次项目更新或者重启,IP地址都会发生改变,如果像微服务那样可以直接使用微服务名称调用来替代地址就好了,尝试一下:
启动两个镜像,由于没有指定–name,使用它自己生成的condescending_lichterman
和infallible_curran
,
ping一下,不行
ning@DESKTOP-1BQCBJ0:~$ docker exec -it condescending_lichterman ping infallible_curran
ping: infallible_curran: Name or service not known
解决方式
-
使用–link
启动的时候使用–link来指定它连接的容器
# 停止所有的容器 docker stop $(docker ps -aq) # 启动容器 # 启动一个centos命名为centos01 docker run -it --name centos01 centos # 再启动一个命名为centos02,并且使用--link连接01 docker run -it --name centos02 --link centos01 centos # 再ping一下 ning@DESKTOP-1BQCBJ0:~$ docker exec -it centos02 ping centos01 PING centos01 (172.17.0.2) 56(84) bytes of data. 64 bytes from centos01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.839 ms 64 bytes from centos01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.134 ms 64 bytes from centos01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.111 ms 64 bytes from centos01 (172.17.0.2): icmp_seq=4 ttl=64 time=0.114 ms 64 bytes from centos01 (172.17.0.2): icmp_seq=5 ttl=64 time=0.178 ms 64 bytes from centos01 (172.17.0.2): icmp_seq=6 ttl=64 time=0.108 ms 64 bytes from centos01 (172.17.0.2): icmp_seq=7 ttl=64 time=0.109 ms 64 bytes from centos01 (172.17.0.2): icmp_seq=8 ttl=64 time=0.112 ms --- centos01 ping statistics --- 8 packets transmitted, 8 received, 0% packet loss, time 287ms rtt min/avg/max/mdev = 0.108/0.213/0.839/0.237 ms
使用01ping一下02
ning@DESKTOP-1BQCBJ0:~$ docker exec -it centos01 ping centos02 centos ping: centos: Name or service not known
反向的不通,看来是02绑定的01是单向的。
查看一下02的容器id使用
inspect
看一下详情docker inspect 0d40035dd984
并没有和绑定相关的。。。看一下02的
hosts
文件:ning@DESKTOP-1BQCBJ0:~$ docker exec -it centos02 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 centos01 ad92ae905a83 172.17.0.3 0d40035dd984
发现02原来是把01的地址配置在
hosts
文件里面了,查看一下01:ning@DESKTOP-1BQCBJ0:~$ docker exec -it centos01 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 ad92ae905a83
--link
就是把要连接的容器的ip地址、容器名称和id配置到自己的hosts文件中来实现的。所以02可以ping通01,01没有配置,ping不通02。。。 -
使用自定义网络network
查看命令:
ning@DESKTOP-1BQCBJ0:~$ docker network --help Usage: docker network COMMAND Manage networks Commands: connect Connect a container to a network create Create a network disconnect Disconnect a container from a network inspect Display detailed information on one or more networks ls List networks prune Remove all unused networks rm Remove one or more networks Run 'docker network COMMAND --help' for more information on a command.
可以看到
create
,创建一个网络,查看一下:ning@DESKTOP-1BQCBJ0:~$ docker network create --help Usage: docker network create [OPTIONS] NETWORK Create a network Options: --attachable Enable manual container attachment --aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[]) --config-from string The network from which to copy the configuration --config-only Create a configuration only network -d, --driver string Driver to manage the Network (default "bridge") --gateway strings IPv4 or IPv6 Gateway for the master subnet --ingress Create swarm routing-mesh network --internal Restrict external access to the network --ip-range strings Allocate container ip from a sub-range --ipam-driver string IP Address Management Driver (default "default") --ipam-opt map Set IPAM driver specific options (default map[]) --ipv6 Enable IPv6 networking --label list Set metadata on a network -o, --opt map Set driver specific options (default map[]) --scope string Control the network's scope --subnet strings Subnet in CIDR format that represents a network segment
创建自定义网络,使用bridge桥接模式
docker network create -d bridge my-bridge-network
# 可以根据命令指定参数,例如子网、网关等 docker network create \ --driver=bridge \ --subnet=172.28.0.0/16 \ --ip-range=172.28.5.0/24 \ --gateway=172.28.5.254 \ br0
查看网络:
ning@DESKTOP-1BQCBJ0:~$ docker network ls NETWORK ID NAME DRIVER SCOPE 128ccbd791ce bridge bridge local 0770dfdc1c7c host host local dfeccced9d2f my-bridge-network bridge local c7cc8e75dd17 none null local
拿到创建的网络
my-bridge-network
的网络id查看其详情:ning@DESKTOP-1BQCBJ0:~$ docker inspect dfeccced9d2f [ { "Name": "my-bridge-network", "Id": "dfeccced9d2fd706cfb317385e241f35fee9feae6271d1d85cc22dfc4781e125", "Created": "2021-09-03T06:58:14.9835961Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ]
使用刚刚创建的网络
my-bridge-network
:启动容器的时候,使用
--network
来将容器添加到my-bridge-network
网络中:# 停止先前的容器 docker stop $(docker ps -aq) # 删掉这两个容器 docker rm $(docker ps -aq) # 启动第一个centos命名为centos01并连接到my-bridge-network网络 docker run -it --name centos01 --network=my-bridge-network centos # 启动第二个centos命名为centos02并连接到my-bridge-network网络 docker run -itd --name centos02 --network=my-bridge-network centos # ping一下 01到02 ning@DESKTOP-1BQCBJ0:~$ docker exec -it centos01 ping centos02 PING centos02 (172.18.0.3) 56(84) bytes of data. 64 bytes from centos02.my-bridge-network (172.18.0.3): icmp_seq=1 ttl=64 time=0.333 ms 64 bytes from centos02.my-bridge-network (172.18.0.3): icmp_seq=2 ttl=64 time=0.089 ms 64 bytes from centos02.my-bridge-network (172.18.0.3): icmp_seq=3 ttl=64 time=0.113 ms 64 bytes from centos02.my-bridge-network (172.18.0.3): icmp_seq=4 ttl=64 time=0.145 ms 64 bytes from centos02.my-bridge-network (172.18.0.3): icmp_seq=5 ttl=64 time=0.068 ms # 反向ping一下 ning@DESKTOP-1BQCBJ0:~$ docker exec -it centos02 ping centos01 PING centos01 (172.18.0.2) 56(84) bytes of data. 64 bytes from centos01.my-bridge-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.162 ms 64 bytes from centos01.my-bridge-network (172.18.0.2): icmp_seq=2 ttl=64 time=0.130 ms 64 bytes from centos01.my-bridge-network (172.18.0.2): icmp_seq=3 ttl=64 time=0.076 ms 64 bytes from centos01.my-bridge-network (172.18.0.2): icmp_seq=4 ttl=64 time=0.172 ms 64 bytes from centos01.my-bridge-network (172.18.0.2): icmp_seq=5 ttl=64 time=0.075 ms
补充没有使用ip来ping的原因:
所有的容器都在docker容器中,docker容器的启动会创建一个网络docker0,也就是
docker network ls
拿到的数组中的1fdad9d9dd06 bridge bridge local
,桥接的模式,容器内的ip都是它分配的,有种路由器的感觉,类似于内网的使用,处于同一内网下的两个机子可以通信,没有使用ip来ping,因为他们都处在docker0的网络下,一定是可以ping通的;而且每次项目启动或者重启都会重新分配一个新的ip,需要重新配置,使用名称来替代更加的方便。