Table of Contents generated with DocToc
简介
Docker是一个开源的应用容器引擎,通过容器可以隔离应用程序的运行时环境(程序运行时依赖的各种库和配置),比虚拟机更轻量(虚拟机在操作系统层面进行隔离)。docker的另一个优点就是build once, run everywhere,只编译一次,就可以在各个平台(windows、linux等)运行。
基本概念
docker的基本概念:
- 镜像(image),类似于虚拟机中的镜像,可以理解为可执行程序。
- 容器(container),类似于一个轻量级的沙盒,可以将其看作一个极简的Linux系统环境。Docker引擎利用容器来运行、隔离各个应用。容器是镜像创建的应用实例,可以创建、启动、停止、删除容器,各个容器之间是是相互隔离的,互不影响。
- 镜像仓库(repository),是Docker用来集中存放镜像文件的地方。注意与注册服务器(Registry)的区别:注册服务器是存放仓库的地方,一般会有多个仓库;而仓库是存放镜像的地方,一般每个仓库存放一类镜像,每个镜像利用tag进行区分,比如Ubuntu仓库存放有多个版本(12.04、14.04等)的Ubuntu镜像。
- dockerfile,image的编译配置文件,docker就是”编译器”。
docker的基本命令:
- docker build:我们只需要在dockerfile中指定需要哪些程序、依赖什么样的配置,之后把dockerfile交给“编译器”docker进行“编译”,生成的可执行程序就是image。
- docker run:运行image,运行起来后就是docker container。
- docker pull:到Docker Hub(docker registry)下载别人写好的image。
图片来源:知乎小灰
docker镜像常用命令
添加docker仓库位置
安装yum-utils:
1 | yum install -y yum-utils device-mapper-persistent-data lvm2 |
添加仓库地址:
1 | yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo |
安装docker服务
1 | yum install docker-ce |
启动 docker 服务
1 | systemctl start docker |
重启docker服务
1 | systemctl restart docker.service |
搜索镜像
1 | docker search java |
下载镜像:
不加版本号,则默认下载最新版本。
1 | docker pull nginx:1.18.0 |
列出镜像
1 | docker images |
删除镜像
删除镜像前必须先删除以此镜像为基础的容器。
1 | docker rmi -f imageID # -f 强制删除镜像 |
删除所有没有引用的镜像(找出IMAGE ID为none的镜像):
1 | docker rmi `docker images | grep none | awk '{print $3}'` |
强制删除所有镜像:
1 | docker rmi -f $(docker images) |
打包镜像
1 | # -t 表示指定镜像仓库名称/镜像名称:镜像标签 .表示使用当前目录下的Dockerfile文件 |
创建镜像
镜像的创建也有两种:
- 利用已有的镜像创建容器之后进行修改,之后commit生成镜像
- 利用Dockerfile创建镜像
利用已有的镜像创建容器之后进行修改
利用镜像启动容器:
1 | [root@xxx ~]# docker run -it java:8 /bin/bash # 启动一个容器 |
exit退出该容器,然后查看docker中运行的程序(容器):
1 | [root@VM_0_7_centos ~]# docker ps -a |
将容器转化为一个镜像,此时Docker引擎中就有了我们新建的镜像,此镜像和原有的java镜像区别在于多了个vim工具。
1 | [root@VM_0_7_centos ~]# docker commit -m "java with vim" -a "tyson" 857aa43eeed4 tyson/java:vim |
运行新建的镜像:
1 | [root@VM_0_7_centos ~]# docker run -it tyson/java:vim /bin/bash |
利用Dockerfile创建镜像
dockerfile用于告诉docker build执行哪些操作。
1 | #该镜像以哪个镜像为基础 |
利用build命令构建镜像:
1 | docker build -t="tyson/java:vim" . |
其中-t用来指定新镜像的用户信息、tag等。最后的点表示在当前目录寻找Dockerfile。
构建完成之后,通过docker images
可以查看生成的镜像。
推送镜像:
1 | # 登录Docker Hub |
docker hub
Docker官方维护了一个DockerHub的公共仓库,里边包含有很多平时用的较多的镜像。除了从上边下载镜像之外,我们也可以将自己自定义的镜像发布(push)到DockerHub上。
- 登录docker hub:
docker login
- 将本地镜像推送到docker hub,镜像的username需要与docker hub的username一致:
docker push tyson14/java:vim
修改镜像存放位置
- 查看镜像存放位置:
1
2docker info | grep "Docker Root Dir"
Docker Root Dir: /var/lib/docker - 关闭docker服务:
1
systemctl stop docker
- 原镜像目录移动到目标目录:
1
mv /var/lib/docker /home/data/docker
- 建立软连接:
1
ln -s /home/data/docker /var/lib/docker
- 再次查看镜像存放位置,发现已经修改。
docker容器常用命令
新建容器
新建并启动容器(docker容器运行必须有一个前台进程, 如果没有前台进程执行,容器认为空闲,就会自行退出。所以需要先创建一个前台进程):
1 | docker run -it --name java java:8 /bin/bash |
- -p:将宿主机和容器端口进行映射,格式为:宿主机端口:容器端口;
- –name:指定容器名称,之后可以通过容器名称来操作容器;
- -e:设置容器的环境变量,这里设置的是时区;
- -v:将宿主机上的文件挂载到容器上,格式为:宿主机文件目录:容器文件目录;
- -d:表示容器以后台方式运行。终端不会输出任何运行信息;
- -i: 以交互模式运行容器,通常与 -t 同时使用;
- -t: 为容器分配一个终端,通常与 -i 同时使用。
使用-it,此时如果使用exit退出,则容器的状态处于Exit,而不是后台运行。如果想让容器一直运行,而不是停止,可以使用快捷键 ctrl+p ctrl+q 退出,此时容器的状态为Up。
创建MySQL容器:
1 | docker run --name mysql4blog -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3307 -d mysql:8.0.20 |
-name
: 给新创建的容器命名,此处命名为mysql4blog
-e
: 配置信息,此处配置MySQL的 root 用户的登录密码-p
: 端口映射,此处映射主机的3307端口到容器的3307端口- -d: 成功启动同期后输出容器的完整ID
- 最后一个
mysql:8.0.20
指的是mysql
镜像
查看容器
列出运行中的容器,-a
参数可以列出所有容器:
1 | docker ps |
停止容器
使用容器名称或者容器ID:
1 | docker stop $ContainerName(or $ContainerId) |
强制停止容器:
1 | docker kill $ContainerName |
启动容器
1 | docker start $ContainerName |
重启容器
1 | docker restart nginx |
进入容器
进入名字为mysql的容器,同时打开命令行终端。使用exit时,容器不会停止。
1 | docker exec -it mysql /bin/bash |
docker attach可以将本机的输入直接输到容器中,容器的输出会直接显示在本机的屏幕上。如果使用exit或者ctrl+c退出,会导致容器的停止。
1 | docker attach container_name/container_id |
新建并运行容器时,使用docker run -it tyson/java:vim /bin/bash
,直接进入容器命令行界面。
使用exit退出命令行之后,重新进入容器:
- 先查询容器id:
docker inspect --format "{{.State.Pid}}" nginx
- 根据查到的容器id进入容器:
nsenter --target 28487 --mount --uts --ipc --net --pid
1
2
3
4
5[root@VM_0_7_centos ~]# docker inspect --format "{{.State.Pid}}" nginx
28487
[root@VM_0_7_centos ~]# nsenter --target 28487 --mount --uts --ipc --net --pid
mesg: ttyname failed: No such device
root@b217a35fc808:/# ls -l
删除容器
根据ContainerName删除容器:
1 | docker rm nginx |
按名称通配符删除容器,比如删除以名称mall-
开头的容器:
1 | docker rm `docker ps -a | grep mall-* | awk '{print $1}'` |
强制删除所有容器:
1 | docker rm -f $(docker ps -a -q) |
容器日志
根据ContainerName查看容器产生的日志:
1 | docker logs nginx |
动态查看容器产生的日志:
1 | docker logs -f nginx |
实时查看日志最后200行:
1 | docker logs -f --tail 200 mysql |
容器ip
1 | docker inspect --format '{{.NetworkSettings.IPAddress}}' nginx |
容器启动方式
1 | # 将容器启动方式改为always |
资源占用
查看指定容器资源占用状况,比如cpu、内存、网络、io状态:
1 | docker stats nginx |
查看所有容器资源占用情况:
1 | docker stats -a |
磁盘使用情况
1 | docker system df |
执行容器内部命令
1 | [root@VM_0_7_centos ~]# docker exec -it nginx /bin/bash |
指定账号进入容器内部:
1 | docker exec -it --user root nginx /bin/bash |
网络
查看网络:
1 | docker network ls |
创建外部网络:
1 | docker network create -d bridge my-bridge-network |
创建容器时指定网络:
1 | docker run -p 33056:33056 --name java \ |
复制文件
将当前目录tpch文件夹复制到mysql容器相应的位置:
1 | docker cp tpch mysql56:/var/lib/mysql #mysql56为容器名 |
容器文件拷贝到宿主机:
1 | docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径 |
docker-compose
Docker Compose是一个用于定义和运行多个docker容器应用的工具。使用YAML文件配置多个应用服务,通过这个YAML文件一次性部署配置的所有服务。
安装
1 | curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose |
修改文件的权限为可执行:
1 | chmod +x /usr/local/bin/docker-compose |
查看是否安装成功:
1 | docker-compose --version |
常用命令
创建、启动容器(默认配置文件docker-compose.yml):
1 | # -d表示在后台运行 |
指定文件启动:
1 | docker-compose -f docker-compose.yml up -d |
停止所有相关容器:
1 | docker-compose stop |
列出所有容器信息:
1 | docker-compose ps |
部署多个服务
- 使用docker-compose.yml定义需要部署的服务;
- 使用docker-compose up命令一次性部署配置的所有服务。
定义配置文件
ports:指定主机和容器的端口映射(HOST:CONTAINER)
volumes:将主机目录挂载到容器(HOST:CONTAINER)
link:连接其他容器(同一个网络下)的服务(SERVICE:ALIAS)
1 | services: |
启动服务
先将docker-compose.yml上传至Linux服务器,再在当前目录下运行如下命令(默认配置文件docker-compose.yml):
1 | docker-compose up -d |
maven插件构建docker镜像
docker镜像仓库
服务器创建docker镜像仓库docker registry:
1 | docker run -d -p 5000:5000 --restart=always --name registry2 registry:2 |
docker开启远程访问
docker开启远程访问的端口2375,修改docker.service文件:
1 | vi /usr/lib/systemd/system/docker.service |
修改内容如下:
1 | ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock |
unix:///var/run/docker.sock
:unix socket,本地客户端将通过这个来连接 Docker Daemon。tcp://0.0.0.0:2375
:tcp socket,表示允许任何远程客户端通过 2375 端口连接 Docker Daemon。
docker支持http上传镜像
1 | echo '{ "insecure-registries":["192.168.3.101:5000"] }' > /etc/docker/daemon.json |
重启docker
使配置生效:
1 | systemctl daemon-reload |
重启docker服务:
1 | systemctl restart docker |
开放端口
1 | firewall-cmd --zone=public --add-port=2375/tcp --permanent |
构建docker镜像
在应用的pom.xml文件中添加docker-maven-plugin的依赖:
1 | <plugin> |
相关配置说明:
- executions.execution.phase:此处配置了在maven打包应用时构建docker镜像;
- imageName:用于指定镜像名称,mall-tiny是仓库名称,
${project.artifactId}
为镜像名称,${project.version}
为版本号; - dockerHost:打包后上传到的docker服务器地址;
- baseImage:该应用所依赖的基础镜像,此处为java;
- entryPoint:docker容器启动时执行的命令;
- resources.resource.targetPath:将打包后的资源文件复制到该目录;
- resources.resource.directory:需要复制的文件所在目录,maven打包的应用jar包保存在target目录下面;
- resources.resource.include:需要复制的文件,打包好的应用jar包。
修改application.yml中的域名,将localhost改为db。可以把docker中的容器看作独立的虚拟机,mall-tiny-docker访问localhost自然会访问不到mysql,docker容器之间可以通过指定好的服务名称db进行访问,至于db这个名称可以在运行mall-tiny-docker容器的时候指定。
1 | spring: |
执行maven的package命令,执行成功之后,镜像仓库会生成mall-tiny-docker镜像。
启动mysql服务:
1 | docker run -p 3306:3306 --name mysql \ |
进入运行mysql的docker容器:docker exec -it mysql /bin/bash
启动mall-tiny-docker服务,通过–link表示在同一个网络内(可以在启动容器时通过–network指定),应用可以用db这个域名访问mysql服务:
1 | docker run -p 8080:8080 --name mall-tiny-docker \ |
其他
给nginx增加端口映射
nginx一开始只映射了80端口,后面载部署项目的时候,需要用到其他端口,不想重新部署容器,所以通过修改配置文件的方式给容器添加其他端口。
1、执行命令docker inspect nginx
,找到容器id
2、停止容器docker stop nginx
,不然修改了配置会自动还原
3、修改hostconfig.json
1 | cd /var/lib/docker/containers/135254e3429d1e75aa68569137c753b789416256f2ced52b4c5a85ec3849db87 # container id |
添加端口:
1 | "PortBindings": { |
4、修改同目录下 config.v2.json
1 | "ExposedPorts": { |
5、重启容器
1 | systemctl restart docker.service # 重启docker服务 |