Docker基础入门getting started

系列文章目录

Docker 概述
Docker getting started



前言

本文主要包含以下内容:

  • 将一个应用放在容器中运行
  • 介绍持久化数据存储方式
  • Docker图形化界面显示方法

一、容器及镜像的概念

容器:

  • 镜像的可运行实例。通过Docker API or CLI可以创建、启动、停止、移动或删除容器。
  • 可在本地、虚拟机、云上运行。
  • 便捷(可在任意OS上运行)。
  • 与其他容器隔离,运行独立的软件、二进制文件、配置。

镜像:
提供隔离的、定制化的文件系统,也包含配置信息、环境变量等。

二、容器化一个应用

git clone https://github.com/docker/getting-started.git
  1. 建立Dockerfile
    用于指示Docker如何创建镜像

Dockerfile

# syntax=docker/dockerfile:1
   
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000
  1. 建立容器镜像
docker build -t getting-started .

docker build命令通过通过 Dockerfile 建立容器镜像。在此过程中Docker下载了许多“layer”。因为是从node:18-alpine开始的,又因本地中没有此镜像,需要先下载。

下载完成后,指令从Docker中拷贝到应用中,并通过yarn安装依赖。CMD指令指定从此镜像启动容器时要运行的默认命令。

最后-t表示给镜像打个标签,如getting-started

最后的.表示从当前目录找查Dockerfile文件
在这里插入图片描述

  1. 启动一个应用容器
docker run -dp 3000:3000 getting-started

-d detached模式
-p在主机端口3000与容器端口3000之间创建端口映射,没有端口映射将无法访问应用

  1. 访问应用
http://localhost:3000
  1. 通过Docker Dashboard可查看运行中的容器

三、更新应用

上章容器化了一个todo应用。本章将更新应用和容器镜像。stop and remove容器。

  1. src/static/js/app.js 修改
...
 -                <p className="text-center">No items yet! Add one above!</p>
 +                <p className="text-center">You have no todo items yet! Add one above!</p>
 ...
  1. docker build
docker build -t getting-started .
  1. 停止,移除容器
# 查看运行中的容器
docker ps
# 停止容器
docker stop <the-container-id>
# 移除容器
docker rm <the-container-id>
# 停止并移除容器
docker rm -f <the-container-id>
  1. start the updated app container
docker run -dp 3000:3000 getting-started

四、分享应用

# 登陆Docker Hub 
docker login -u YOUR-USER-NAME
# 添加tag
docker tag getting-started YOUR-USER-NAME/getting-started
# push
docker push YOUR-USER-NAME/getting-started

五、持久化数据存储

容器从镜像的“层”中获取该容器的文件系统,即便是从统一镜像实例的两个容器也是隔离的,两个容器之间的更改不互通。

# 运行容器,并执行命令 bash ......
docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
# 查看运行中的容器 -a 查看所有容器
docker ps
# 在容器中执行命令
docker exec <container-id> cat /data.txt
# 然后再run另一个容器,次容器中则无data.txt文件

volume mount 和 bind mount比较

Named volumesBind mounts
共享文件存放在主机的位置由Docker选择用户决定
mount示例 (using --mount)type=volume,src=my-volume,target=/usr/local/datatype=bind,src=/path/to/data,target=/usr/local/data
用容器内容填充新卷YN
支持卷驱动程序YN

Container volumes

Volumes可将容器中的某一文件系统路经连接至本地主机上。如果在容器总挂载了该目录,其变更也在宿主机上可见。如果我们跨容器重新启动装载相同的目录,我们将看到相同的文件。

# create volume
docker volume create <filename>
# 在run一个镜像时加上volume,volume文件所在的目录就成了volume目录
docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
# rm上面的容器后再用相同的命令即可实现在多个容器中共享数据

# docker volume <filename> 的存放位置
docker volume inspect todo-db
[
    {
        "CreatedAt": "2022-09-26T02:18:36Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

bind mounts

docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash

src为host的目录,target为容器的目录
运行此条命令后 host的"$(pwd)"目录和 容器的/src目录实时同步

在容器中运行宿主机中正在开发的应用

docker run -dp 3000:3000 \
    -w /app --mount type=bind,src="$(pwd)",target=/app \
    node:18-alpine \
    sh -c "yarn install && yarn run dev"
  • dp 3000:3000 分离模式,指定host和容器的端口映射(用于访问app网页)
  • -w /app 设置命令行的工作目录
  • --mount type=bind, src="$(pwd)", target=/app bind mount 宿主机目录(“$(pwd)”)和容器目录(/app)
  • node:18-alpine 使用的镜像
  • sh -c "yarn install && yarn run dev" 容器启动后运行的命令。使用sh(node:18-alpine没有bash) 运行 yarn install 安装包,然后运行 yarn run dev 启动 该软件。如果查看下 package.json,dev脚本启动了nodemon
docker logs -f <container-id>
nodemon src/index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000

六、跨多容器的应用

APP放在一个容器中,MySQL放在另一个容器中
在这里插入图片描述
默认情况下容器与其它容器、进程是隔离的。多个容器之间可通过网络进行通讯,同一个网络下的容器才可进行通讯。

  1. 创建网络
docker network create <app name todo-app>
  1. 启动MySQL容器,并将其附着在网络上
docker run -d \
     --network todo-app --network-alias mysql \
     -v todo-mysql-data:/var/lib/mysql \
     -e MYSQL_ROOT_PASSWORD=secret \
     -e MYSQL_DATABASE=todos \
     mysql:8.0
  1. 验证2是否成功
docker exec -it <mysql-container-id> mysql -u root -p
mysql> SHOW DATABASES;
+--------------------+
 | Database           |
 +--------------------+
 | information_schema |
 | mysql              |
 | performance_schema |
 | sys                |
 | todos              |
 +--------------------+
 5 rows in set (0.00 sec)
mysql> exit

连接MySQL

  1. 启动一个新的容器,连接到同一个network
    此处用到的image为 nicolaka/netshoot
docker run -it --netword <netword-file> <imagename>

                    dP            dP                           dP   
                    88            88                           88   
88d888b. .d8888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P 
88'  `88 88ooood8   88   Y8ooooo. 88'  `88 88'  `88 88'  `88   88   
88    88 88.  ...   88         88 88    88 88.  .88 88.  .88   88   
dP    dP `88888P'   dP   `88888P' dP    dP `88888P' `88888P'   dP   
                                                                    
Welcome to Netshoot! (github.com/nicolaka/netshoot)

找到 hostname为 mysql的IP

dig mysql

; <<>> DiG 9.18.11 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38459
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;mysql.				IN	A

;; ANSWER SECTION:
mysql.			600	IN	A	172.18.0.2

;; Query time: 3 msec
;; SERVER: 127.0.0.11#53(127.0.0.11) (UDP)
;; WHEN: Tue Feb 14 13:52:52 UTC 2023
;; MSG SIZE  rcvd: 44

其中mysql不仅仅是一个有效的hostname,Docker还会把他解析成IP地址,即--network-alias mysql与该IP有映射关系。
也就是说应用只需要连接到hostname为 mysql 的容器即可实现容器间通讯。

  1. 将APP连接到MySQL
    在/app目录下
docker run -dp 3000:3000 \
   -w /app -v "$(pwd):/app" \
   --network todo-app \
   -e MYSQL_HOST=mysql \
   -e MYSQL_USER=root \
   -e MYSQL_PASSWORD=secret \
   -e MYSQL_DB=todos \
   node:18-alpine \
   sh -c "yarn install && yarn run dev"
查看进度
docker logs -f <container-id>
查看数据库
docker exec -it <mysql-container-id> mysql -p todos

mysql> select * from todo_items;
+--------------------------------------+------+-----------+
| id                                   | name | completed |
+--------------------------------------+------+-----------+
| f207cb07-c947-4d37-aef0-4b0dc50044d5 | abc  |         0 |
| d1e7dc53-fb06-4001-96a5-a5dc142e90ba | dev  |         1 |
| 8279b8a3-383b-4be4-bd4b-002a1111b44e | sdf  |         0 |
+--------------------------------------+------+-----------+
3 rows in set (0.01 sec)

七、Docker 其它

检查是否安装了Docker 组件

docker compose version

Docker 组件可帮助快速构建跨容器的应用,配置好后只需一条命令即可其多多容器应用。

其它:

# 扫描docker 镜像的漏洞
docker scan <image-name>

# 查看镜像的layers
docker image history <image-name>

# 通过Layer caching加速镜像的构建等

八、Docker 图形化界面显示

把docker镜像看做一台没配显示器的电脑,程序可以运行,但是没地方显示。

而linux目前的主流图像界面服务X11又支持客户端/服务端(Client/Server)的工作模式。

只要在容器启动的时候,将『unix:端口』或『主机名:端口』共享给docker,docker就可以通过端口找到显示输出的地方,和linux系统共用显示。

# 在本地机上安装x11界面服务
apt-get install x11-xserver-utils
# 在为所有用户开放权限,访问X11的显示接口
# xhost + 每次重新开机,需要在本机操作一次
xhost +

# 再启动容器
docker run -it \
    -v /tmp/.x11-unix:/tmp/.x11-unix \             # 共享本地 unix 端口
    -e DISPLAY=unix$DISPLAY \                      # 修改环境变量DISPLAY
    -e GDK_SCALE \                       # 这两个是与显示效果相关的环境变量
    -e GDK_DPI_SCALE --net=host ubuntu /bin/bash   

容器启动后,在容器中安装个小程序测试是否成功

# apt-get update
apt-get install xarclock
xarclock

九、docker 必备命令

pull
push
build
run
commit
start, stop, rm
registry
image
Dockerfile
容器
本地电脑
volume, bind
容器
容器
容器
network
容器
exec
attch
host
容器

容器相关命令

start, stop, restart, rm, ps

docker start [OPTIONS] CONTAINER [CONTAINER...]  # 启动一个或多个容器
Options:
  -a, --attach               Attach STDOUT/STDERR and forward signals
  -i, --interactive          Attach container's STDIN
默认是非交互式, 与终端分离

docker stop 容器ID
docker restart 容器ID
# 移除容器
docker rm <the-container-id>
# 停止并移除容器
docker rm -f <the-container-id>
# 移除所有容器
docker rm -f $(docker ps -aq)

容器进入与退出

# 在容器中执行命令
docker exec <container-id> cat /data.txt
# 进入容器
docker exec -it 容器名/容器ID /bin/bash
# docker attach 容器名/容器ID , 不推荐

docker exec -it ID ls  # 在运行中的容器中执行命令

# run容器
docker run -it --name 启动后的名字 --network <name[如:host]> -v /home/ubuntu/宿主机:/home/容器内 镜像名或ID /bin/bash
	- it:运行一个交互式容器
	- --name可以为容器指定一个名称,使得容器更易于识别和管理
	- -v 选项可以将主机上的目录或文件挂载到容器内部
		--mount提供更细粒度,-v则是粗粒度的
	- --network 容器可访问方网络
# 第二次运行docker环境
docker start -ai 启动后的名字

#-----直接退出  未添加 -d(持久化运行容器) 时 执行此参数 容器会被关闭  
exit
# 优雅退出 --- 无论是否添加-d 参数 执行此命令容器都不会被关闭
Ctrl + p + q

镜像相关命令

删除镜像 ------当前镜像没有被任何容器使用才可以删除

# 查看所有镜像
docker images
# 删除镜像
docker rmi 镜像ID
#删除全部镜像  -a 意思为显示全部, -q 意思为只显示ID
docker rmi -f $(docker images -aq)

镜像制作与推送

# docker login 
# commit镜像
docker commit -m "basic ubuntu env" -a "teacherz" 容器ID \
# [用户名/仓库名[:tag]]
teacherz/basic_ubuntu:basic_ubuntu_env

# 推送到远程
docker push teacherz/basic_ubuntu:basic_ubuntu_env

助记

-i  交互式
-t  attach 附着
-d  dettach 分离
-p  port 指定端口

docker register deploy

https://hub.docker.com/_/registry
https://distribution.github.io/distribution/about/deploying/
https://distribution.github.io/distribution/about/configuration/

$ docker run -d -p 5000:5000 --restart always --name registry registry:2

$ docker pull ubuntu
$ docker tag ubuntu localhost:5000/ubuntu
$ docker push localhost:5000/ubuntu

#  change the port the registry listens on within the container
# use the environment variable REGISTRY_HTTP_ADDR to change it. 
# listen on port 5001 within the container:
$ docker run -d \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:5001 \
  -p 5001:5001 \
  --restart always \
  --name registry-test \
  registry:2

上述指令默认将镜像存储在容器的/var/lib/registry/目录下,可通过-v将其映射到本地,也可通过修改配置改变默认存储目录

使用Docker Registry HTTP API获取镜像信息
使用 v2/_catalog 端点获取注册表中的所有仓库(repository)列表。

curl -X GET http://localhost:5000/v2/_catalog

获取仓库的所有标签

curl -X GET <registry-url>/v2/<repository>/tags/list

docker 去掉 sudo

  1. 查看用户组及成员
sudo cat /etc/group | grep docker
  1. 添加docker组
sudo groupadd docker 
  1. 添加用户到docker组
sudo gpasswd -a ${USER} docker 
  1. 增加读写权限
 sudo chmod a+rw /var/run/docker.sock
  1. 重启docker
sudo systemctl restart docker 

references

Docker 图形化界面显示 https://zhuanlan.zhihu.com/p/460494660

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值