linux系统下docker教程基础篇

docker安装

1.卸载旧版本的docke

yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

2.yum安装需要的安装包

yum install -y yum-utils

3.配置docker安装包的仓库

#官方版本,较慢,不推荐(国外版本)
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

#阿里云的镜像仓库,推荐使用
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

4.更新yum软件包的索引

yum makecache fast

5. 安装docker

yum install docker-ce docker-ce-cli containerd.io

 6.启动docker

systemctl start docker

7.使用docker version测试是否安装成功,出现如下证明成功

[root@localhost /]# docker version
Client: Docker Engine - Community
 Version:           19.03.13  
 API version:       1.40  
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 17:03:45 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community 
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:02:21 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

 8.hello-world镜像测试

##包含的信息1-5
[root@localhost /]# docker run hello-world  # 1.运行镜像                                 
Unable to find image 'hello-world:latest' locally  # 2.发现本地没有
latest: Pulling from library/hello-world  # 3.因为2所以会从远程仓库拉取。如果远程也没有会报错
0e03bdcc26d7: Pull complete  # 4.拉取完成
Digest: sha256:8c5aeeb6a5f3ba4883347d3747a7249f491766ca1caa47e5da5dfcf6b9b717c0
Status: Downloaded newer image for hello-world:latest

Hello from Docker!  # 5.并且run
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

9.验证8,直接run的话,如果本地没有会从远程仓库拉取,发现的确拉取了

[root@localhost /]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        9 months ago        13.3kB

10.拓展:卸载docker

# 1.卸载Docker Engine, CLI, and Containerd packages
yum remove docker-ce docker-ce-cli containerd.io
# 2.删除所有images, containers, and volumes
rm -rf /var/lib/docker

镜像命令

docker images     查看本地所有的镜像

docker search     搜索镜像

docker pull    下载/拉取镜像到本地

docker rmi    删除镜像

容器命令

docker run [可选参数] image

可选参数:

--name="自定义名称"    自定义容器的名称,起别名

-d    后台方式运行

-it    使用交互方式运行,进入容器查看内容(进入容器的shell界面)

-p    指定容器的端口,如:-p 80:8080

        -p  IP:主机端口:容器端口

        -p  主机端口:容器端口(常用)

        -p  容器端口

-P    随机指定端口

docker ps    列出所有正在运行的容器

可选参数:

不加可选参数    列出当前正在运行的所有容器

-a    列出当前正在运行的容器+带出历史运行过的容器

-q    只显示容器的容器ID

-n=num    显示最近创建的容器

退出容器

exit    直接容器停止并退出

Ctrl + P + Q    容器不停止退出

docker rm container-id    删除容器(注意和docker rmi的区别,带i表示是image镜像),但是不能删除正在运行的容器

可选参数:

-f    强制删除容器,可以删除正在运行的容器

-f $(docker ps -qa)    强制删除所有的容器

启动和停止容器的操作

docker start container-id    启动容器

docker restart container-id    重启容器

docker stop container-id    关闭容器

docker kill container-id    强制停止容器

常用其它命令

docker run -d 镜像名

坑:用docker ps命令发现centos停止了。原因就是docker容器使用后台运行的话,就必须在镜像里面有运行的其他服务或者说是必须有前台应用,否则就会认为没有意义,就会自动退出。再举个例子,比如run一个nginx的镜像,里面不做任何配置,run -d启动容器后,发现自己没有对外提供服务,就会立刻停止

docker logs  容器ID    查看日志

可选项:

-tf 容器id    查看全部日志

-tf --tail num条数    查看最后的num条日志

docker top container-id    查看容器的进程id

docker inspect container-id    查看容器的元数据信息

进入当前正在运行的容器,两种方式

  1. docker exec  容器id    进入容器后开启一个新的终端进程,可以在里面操作shell命令(常用)
  2. docker attach 容器id    进入容器正在运行的输入输出的终端,不会启动新的可以进行命令的界面
  3. 另外还可以在run的过程中直接进入
    docker run -d --name centos  f35646e83998 /bin/bash

docker cp 容器ID:容器内文件路径  目的地主机路径    从容器内拷贝文件到宿主主机(手动拷贝)

命令小结

attach            # 当前shell下attach连接到指定运行的容器
build             # 通过Dockerfile定制镜像
commit            # 提交当前容器为新的镜像
cp                # 从容器内拷贝指定文件或者目录到指定宿主主机
create            # 创建一个新的容器,同run,但是不启动容器
diff              # 查看docker容器变化
events            # 从docker服务获取容器实时事件
exec              # 在已存的容器上运行命令
export            # 将容器内容以流的形式导出一个tar归档文件,对应import
history           # 展示指定容器的形成历史
images            # 列出所有images镜像
import            # 从tar包中的内容创建一个新的系统文件镜像,对应export
info              # 显示系统信息
inspect           # 查看容器的详细信息
kill              # kill指定容器
load              # 从一个tar包中加载一个镜像,对应save
login             # 注册或登录一个docker源服务器
logout            # 从当前docker registry退出
logs              # 输出当前容器日志信息
port              # 查看映射端口对应的容器内容部源端端口
pause             # 暂停容器
ps                # 列出运行的容器列表
pull              # 从docker镜像源服务器仓库拉取并下载指定镜像或者库
push              # 推送指定镜像或者库到docker源服务器仓库
restart           # 重启运行的容器
rm                # 移除一个或多个容器
rmi               # 移除一个或多个镜像(-f可强制删除有对应容器运行的镜像)
run               # 创建一个新的容器并运行一个命令
save              # 保存一个镜像为一个tar归档包,对应load
search            # 在docker hub中搜索镜像
start             # 启动容器
tag               # 给本地镜像打标签
top               # 查看容器中运行的进程信息
unpause           # 取消暂停容器
version           # 查看docker版本号
wait              # 截取容器停止时的退出状态值

数据卷挂载(在宿主机共享数据或用来宿主机的持久化备份)

数据卷挂载添加数据卷有两种方式,一种是通过命令挂载,一种是通过dockerfile制作镜像的时候直过载(下面有具体的实现教程)。这里只来演示第一种方式

docker run -it -v  /宿主机绝对路径目录:  /容器内绝对目录  镜像名

首先在宿主机上执行下面命令,将宿主机/home/testvolume和容器内/home/testvolume两个目录同步。此时都只有目录

[root@localhost home]# docker run -it -v /home/testvolume:/home/testvolume 0d120b6ccaa8
[root@ec295878cab7 /]#   ##执行run后自动进入到容器的bash界面了

然后在打开一个新的宿主机的bash界面,在/home/testvolume创建文件

[root@localhost home]# cd testvolume/
[root@localhost testvolume]# vim a.txt
[root@localhost testvolume]# cat a.txt 
 update on linux

回到刚刚进入容器的界面测试:

[root@ec295878cab7 home]# cd testvolume/
[root@ec295878cab7 testvolume]# ls
a.txt
[root@ec295878cab7 testvolume]# cat a.txt 
 update on linux

当然,也可以在容器内进行修改,在宿主机同样也可以发现数据发生了同步。

联合文件系统UnionFS

目的:深入理解docker镜像images(以及其中的layer)、容器container(以及通过commit生成一个新的镜像image)、Dockerfile(自己制作镜像image)

Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
 
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
 
rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。 
。 
 平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M??

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
 

Docker镜像都是只读的
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。也就是说镜像是只读的,只能通过run命令执行,执行生成的东西就是容器container,而这个container容器是可写的,可以进入该容器进行写(编辑修改)里面的内容。当然该容器也可以通过commit命令生成一个新的只读镜像供其他地方使用或备份。

docker中的层级layer

Docker使用层layer创建镜像,Dockerfile中每一个命令都会创建一个新的层layer,每层都包含执行命令前后的状态之间镜像的文件系统更改。同理,通过commit生成的新的镜像也是这样的结构。

当然,如果是pull命令获取image镜像的时候也可以看到次中分层的现象

commit命令和Dockerfile

之所以放到一起,是因为这两个都是可以用来制作镜像的,区别是docker commit命令是通过制定镜像执行run命令生成了容器,然后进入到该容器的bash命令,对该容器进行了某些内容的修改,然后就可以通过commit命令生成一个新的镜像,算是对某个镜像的修改,Dockerfile是自己制作镜像,所有的内容都是自己写的,而不是通过模板镜像修改来的。

docker commit container-id  通过某个容器id,将该修改后的容器生成一个新的镜像。

这里我们用centos的镜像来做说明和讲解。拉取的centos为精简版,缺少很多命令,比如ifconfig

# 第一步:通过pull从docker hub中拉取centos镜像
[root@localhost home]# docker pull centos

# 第二步:获取下载好的镜像的id
[root@localhost home]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              0d120b6ccaa8        2 months ago        215MB

# 第三部:通过交互方式run该镜像
[root@localhost home]# docker run -it 0d120b6ccaa8
[root@2a283e72e4f3 /]#   ##已经证明已经进入了centos镜像run命令的容器,2a283e72e4f3就是容器id

##此时发现没有ifconfig
[root@2a283e72e4f3 /]# ifconfig
bash: ifconfig: command not found

##那我们就通过此容器制作一个带有ifconfig命令的容器
[root@2a283e72e4f3 /]# yum install net-tools

##安装完成之后,次容器就有了ifconfig命令,然后通过exit命令退出容器,回到宿主机
[root@2a283e72e4f3 /]# exit
[root@localhost home]#

##通过docker commit 容器id的命令生成一个带有ifconfig命令的centos镜像
## docker commit -m="XX" -a="XX" CONTAINER-ID IMAGE-NAME:TAG
## -m 要制作的镜像的描述信息  -a 作者信息  
## CONTAINER-ID  进入交互模式的时候已经显示了,或者可以通过docker images查看
## IMAGE-NAME 定义要制作的镜像的名称
## TAG 标签,一般指版本号
[root@localhost home]# docker commit -m="mycentos with ifconfig" -a="BooleanZhang" 2a283e72e4f3 mycentos:0.1

##到此,已经通过commit命令改造出了新的镜像,可以像拉取的镜像一样使用了,并且有了ifconfig命令

Dockerfile  制作镜像,docker命令必须全部大写

现在我们不要从docker hub中拉取,直接来自己制作镜像,从生成过程也可以看出layer效果

# 创建dockerfile文件,并编写具体的内容
[root@localhost home]# vim dockerfile
##文件内容
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "=============end=========="
CMD /bin/bash
##文件内容结束,然后保存退出。

# 通过docker build命令生成镜像,一定要注意:最后有个点“.”
## -f 编写的dockerfile文件   -t 要生成的镜像名称 
[root@localhost home]# docker build -f dockerfile -t myDockerFileImage .
## 镜像生成开始的输出过程 start
Sending build context to Docker daemon  5.632kB
Step 1/4 : FROM centos
 ---> 0d120b6ccaa8  
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in abd69e7a14fa   
Removing intermediate container abd69e7a14fa
 ---> 08a914df3ba8
Step 3/4 : CMD echo "=============end=========="
 ---> Running in 29fef15a5448
Removing intermediate container 29fef15a5448
 ---> f245f54d891c
Step 4/4 : CMD /bin/bash
 ---> Running in 1d05f1c76eb7
Removing intermediate container 1d05f1c76eb7
 ---> a4d9b3307e33
Successfully built a4d9b3307e33
Successfully tagged mydockerfileimage:latest
## 镜像生成开始的输出过程 end
#####从生成过程也可以看出镜像是分层的,多个layer组成了一个镜像

# 查看已经生成的镜像,
[root@localhost home]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mydockerfileimage   latest              a4d9b3307e33        5 seconds ago       215MB

# 测试自己定义的镜像
[root@localhost home]# docker run -it a4d9b3307e33
[root@f191184f9936 /]# exit           
exit
# 查看自己编写的dockerfile文件中的数据卷挂载
[root@localhost home]# docker inspect f191184f9936

验证挂载信息如下:是正常的,且是匿名挂载

自定义docker网络

docker network create --driver mode --subnet 子网/域 --gateway 网关 自定义网络的名称

docker 0和--link 方式可以参照一篇别人写的博客,很详细https://blog.csdn.net/mgdj25/article/details/106290826。这里只做自定义网络的过程

# 自定义docker的网络
##docker network create --driver mode --subnet 子网/域 --gateway 网关 自定义网络的名称
[root@localhost testvolume]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
d6dedb2309be5e7346827e214c65aeb33a19d871a2f8d8ed4d60cb1114b2aa1f

##这样一个自定义网络就建立起来了,docker network ls然后查看
[root@localhost testvolume]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
e559113fad0b        bridge              bridge              local
ffa123fcf52d        host                host                local
d6dedb2309be        mynet               bridge              local
52d37e69d11a        none                null                local


# 都利用自己的网络启动两个tomcat,需要--net mynet 指定使用我们自定义的网络 -P 随机端口
[root@localhost home]# docker run -d -P --net mynet --name tomcat-mynet-01 tomcat
[root@localhost home]# docker run -d -P --net mynet --name tomcat-mynet-02 tomcat


[root@localhost testvolume]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
4afa2bf609d4        tomcat              "catalina.sh run"   3 minutes ago       Up 3 minutes        0.0.0.0:32770->8080/tcp   tomcat-mynet-02
efaaa6de31a7        tomcat              "catalina.sh run"   3 minutes ago       Up 3 minutes        0.0.0.0:32769->8080/tcp   tomcat-mynet-01

# 这时不管是从宿主机与任意容器相互ping,还是容器间相互ping都是可以ping通的
[root@localhost]# docker exec -it 4afa2bf609d4 ping efaaa6de31a7
[root@localhost]# docker exec -it   tomcat-mynet-02 ping efaaa6de31a7

[root@localhost]# ping 4afa2bf609d4

[root@localhost testvolume]# docker exec -it efaaa6de31a7 /bin/bash
root@efaaa6de31a7:/usr/local/tomcat# ping tomcat-mynet-02
PING tomcat-mynet-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-mynet-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.027 ms

网络连通(跨网络之间容器连通)

        docker network connect NET-NAME CONTAINER-ID   将网络和容器连接

上面我们测试的是同一个网络之间,是可以互相ping同的,但是如果不在同一个网络中,就不可以互相通了。比如我们不指定我们的网络,利用docker0来启动一个tomcat,然后测试这个tomcat容器和我们利用mynet启动的tomcat容器互相ping,这就不行了

# 利用默认docker0 启动tomcat
[root@localhost home]# docker run -d -P  --name tomcat-docker0 tomcat        
791a140cba55cb40040409b91b2c0df0df1cd640ec3de9c2afbcd033d030545e
[root@localhost home]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
791a140cba55        tomcat              "catalina.sh run"   5 seconds ago       Up 4 seconds        0.0.0.0:32773->8080/tcp   tomcat-docker0
4afa2bf609d4        tomcat              "catalina.sh run"   36 minutes ago      Up 36 minutes       0.0.0.0:32770->8080/tcp   tomcat-mynet-02
efaaa6de31a7        tomcat              "catalina.sh run"   36 minutes ago      Up 36 minutes       0.0.0.0:32769->8080/tcp   tomcat-mynet-01

# 发现docker0网络下的tomcat-docker0和mynet网络的tomcat-mynet-01互相ping不通
[root@localhost home]# docker exec -it tomcat-docker0 ping tomcat-mynet-01
ping: tomcat-mynet-01: Name or service not known    


# 利用docker network connect NET-NAME CONTAINER-ID将网络和容器连接
[root@localhost home]# docker network connect mynet tomcat-docker0

# 测试是否连通,发现已经打通不同网络的容器
[root@localhost home]# docker exec -it  tomcat-mynet-01 ping tomcat-docker0
PING tomcat-docker0 (192.168.0.5) 56(84) bytes of data.
64 bytes from tomcat-docker0.mynet (192.168.0.5): icmp_seq=1 ttl=64 time=0.064 ms
64 bytes from tomcat-docker0.mynet (192.168.0.5): icmp_seq=2 ttl=64 time=0.039 ms
^C

探究mynet为啥?

# 查看我们自定义的网络信息
[root@localhost home]# docker network inspect mynet

发现将容器加入到了mynet中。docker network connect NET-NAME CONTAINER-ID命令的实质是将container加入到了我们自定义的网络中,以此来实现了跨网络容器的互相通信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值