简介
之前就了解过Docker最简单但是不准确的理解是:轻量级的虚拟机
不得不说虚拟化这一话题始终贯穿,从分时操作系统到RAID,从虚拟机到云原生都有它的思想
三个概念
- 镜像(Image):类似于虚拟机中的镜像,是一个包含有文件系统的面向Docker引擎的只读模板。任何应用程序运行都需要环境,而镜像就是用来提供这种运行环境的。
- 容器(Container):容器是镜像创建的应用实例,可以创建、启动、停止、删除容器,各个容器之间是是相互隔离的,互不影响。注意:镜像本身是只读的,容器从镜像启动时,Docker在镜像的上层创建一个可写层,镜像本身不变。
- 仓库(Repository):类似于代码仓库,这里是镜像仓库,是Docker用来集中存放镜像文件的地方。注意与注册服务器(Registry)的区别:注册服务器是存放仓库的地方,一般会有多个仓库;而仓库是存放镜像的地方,一般每个仓库存放一类镜像,每个镜像利用tag进行区分,比如Ubuntu仓库存放有多个版本(12.04、14.04等)的Ubuntu镜像。
Hello World
-
打开terminal,输入
docker version,查看安装是否成功Client: Cloud integration: v1.0.20 Version: 20.10.10 API version: 1.41 Go version: go1.16.9 Git commit: b485636 Built: Mon Oct 25 07:43:15 2021 OS/Arch: darwin/amd64 Context: default Experimental: true Server: Docker Engine - Community Engine: Version: 20.10.10 API version: 1.41 (minimum version 1.12) Go version: go1.16.9 Git commit: e2f740d Built: Mon Oct 25 07:41:30 2021 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.4.11 GitCommit: 5b46e404f6b9f661a205e28d59c982d3634148f8 runc: Version: 1.0.2 GitCommit: v1.0.2-0-g52b36a2 docker-init: Version: 0.19.0 GitCommit: de40ad0 -
docker run hello-world
➜ ~ docker run hello-world
Hello from Docker!
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/
docker run命令根据image启动container
Docker首先检查本地是否拥有该image,没有的话从Repository下载,然后运行
由于之前我运行过docker pull hello-world,所以这里没有下载过程
ubuntu
docker run -it ubuntu bash
➜ ~ docker run -it ubuntu bash
root@4601014882cf:/# pwd
/
root@4601014882cf:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
root@4601014882cf:/#
参数说明:
- -i: 交互式操作。
- -t: 终端。
- ubuntu: ubuntu 镜像。
- /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
要退出终端,直接输入 exit:
其他命令
拉取docker镜像
docker pull image_name
查看宿主机上的镜像,Docker镜像保存在/var/lib/docker目录下:
docker images
删除镜像
docker rmi image_name
查看当前有哪些容器正在运行,下述两个命令等价
docker ps
docker container ls
查看所有容器
docker ps -a
启动、停止、重启容器命令:
docker start container_name/container_id
docker stop container_name/container_id
docker restart container_name/container_id
后台启动一个容器后,如果想进入到这个容器,可以使用attach命令:
docker attach container_name/container_id
删除容器的命令:
docker rm container_name/container_id
查看当前系统Docker信息
docker info
从Docker hub上下载某个镜像:
docker pull centos:latest
docker run的参数:
-d 分离终端
-P 随机地把容器中所有暴露的端口映射到本地端口
--name 指定容器名字
--rm 本次运行完就自动删除此容器
Terminology
-
Images - The blueprints of our application which form the basis of containers.
-
Containers - Created from Docker images and run the actual application.
-
Docker Daemon - The background service running on the host that manages building, running and distributing Docker containers. The daemon is the process that runs in the operating system which clients talk to.
-
Docker Client - The command line tool that allows the user to interact with the daemon.
-
Docker Hub - A registry of Docker images. You can think of the registry as a directory of all available Docker images.
创建自己的image
概念
- 分类1
- base image:image that have no parent image
- child image:基于base image增加了功能
- 分类2
- official image:officially maintained and supported by the folks at Docker. one word long.
- user image:created and shared by users.
user/image-name.
Dockerfile
Dockerfile告诉Docker在创建image的时候该怎么做,是文本文件
提交操作
docker push username/image_name
部署到AWS
待完成😇😇
MULTI-CONTAINER ENVIRONMENTS
把每个服务的沙盒分开是明智的
这是Docker在微服务时代🔥的原因
Docker网络
docker network ls 查看当前的网络
NETWORK ID NAME DRIVER SCOPE
1d6b5782ac77 bridge bridge local
be2f04acafd5 host host local
17b1da316665 none null local
docker network inspect bridge 仔细审视某个网络
[
{
"Name": "bridge",
"Id": "1d6b5782ac776413ca219307ba709776bab08e0b7d0043dd21dad2fd1fe2bd8d",
"Created": "2021-11-24T01:43:19.15368684Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"658636b7a5898f5323aaae3cbd04b7855a8c9bfb24bdc71c1d0216ad935e59aa": {
"Name": "es",
"EndpointID": "a8dbadeeb5bf480c65b5337f9926ff9503f8230e4a124060dd054a841ae790f7",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"f37cb6348fac669786a4d333f5ca6faac54fef1da5c74518c76647755b54f15f": {
"Name": "funny_hoover",
"EndpointID": "9362e7fc00222c67e7dccdb1929bf215a7cc00e405dde868887d9c4f5c4d3ec6",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"tspz77nox8bd1m7labzjclgdm": {
"Name": "tspz77nox8bd1m7labzjclgdm",
"EndpointID": "b859aed856aad0622d211756138656aa9d64cab260c048eb00bb8aafbe939856",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
我看看到有很多container在bridge上工作,container创建时默认在bridge上
一些命令
- 新建网络
docker network create foodtrucks-net
- 指定容器运行在哪个网络上
docker run --net foodtrucks-net
automatic service discovery
containers can not only communicate by IP address, but can also resolve a container name to an IP address
example
foodtrucks-web 需要从ES 处获得HTTP response
➜ ~ docker run -P --rm zhenglinli/foodtrucks-web
/usr/local/lib/python3.6/dist-packages/requests/__init__.py:91: RequestsDependencyWarning: urllib3 (1.26.7) or chardet (3.0.4) doesn't match a supported version!
RequestsDependencyWarning)
Unable to connect to ES. Retrying in 5 secs...
Unable to connect to ES. Retrying in 5 secs...
Unable to connect to ES. Retrying in 5 secs...
Out of retries. Bailing out...
目前是连接不上的,因为不在同一个网络下
目前,ES在http://localhost:9200/上运行,可以通过本机访问但是不能在容器里访问
在容器中,我们通过docker network inspect bridge来查看运行在bridge网络上的情况
➜ ~ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "1d6b5782ac776413ca219307ba709776bab08e0b7d0043dd21dad2fd1fe2bd8d",
"Created": "2021-11-24T01:43:19.15368684Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"658636b7a5898f5323aaae3cbd04b7855a8c9bfb24bdc71c1d0216ad935e59aa": {
"Name": "es",
"EndpointID": "a8dbadeeb5bf480c65b5337f9926ff9503f8230e4a124060dd054a841ae790f7",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
我们看到,容器中我们可以通过172.17.0.3:9200来访问ES
➜ ~ docker run -it --rm zhenglinli/foodtrucks-web bash
root@227190b18e94:/opt/flask-app# curl 172.17.0.2:9200
curl: (7) Failed to connect to 172.17.0.2 port 9200: Connection refused
root@227190b18e94:/opt/flask-app# curl 172.17.0.3:9200
{
"name" : "oyVim2N",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "rBB5jgUIRMSnb4PHPCD3Xw",
"version" : {
"number" : "6.3.2",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "053779d",
"build_date" : "2018-07-20T05:20:23.451332Z",
"build_snapshot" : false,
"lucene_version" : "7.3.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
两个问题:
- 不同
container间怎么通信? - 怎么确保隔离?
- 我们创建自己的网络
foodtrucks-net,用于es和foodtrucks-web的 通信:
docker network create foodtrucks-net
- 在网络
foodtrucks-net上,启动es:
docker run -d --name es --net foodtrucks-net -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
查看网络上的情况:
docker network inspect foodtrucks-net
➜ ~ docker network inspect foodtrucks-net
[
{
"Name": "foodtrucks-net",
"Id": "9deb3da791fd3d709c99f4152fb055e9f5744dc83adf1c692b732ff3f98c942f",
"Created": "2021-11-24T04:11:13.5456846Z",
"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": {
"7231ee0b0e2feb1084cb136cc2aa2b1fef7d5a0b076b6d76a72a5c759a7af7ae": {
"Name": "es",
"EndpointID": "ada4f19a762b810c8949d5f2286dc7db63139582f7af84f0ec28ab67835af38f",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
es container is now running inside the foodtrucks-net bridge network
- 启动
foodtrucks-web
docker run -d --net foodtrucks-net -p 5000:5000 --name foodtrucks-web zhenglinli/foodtrucks-web
Kubernetes
it can make dealing with multi-container apps easier.