引用
新手-Linux
克隆实验室仓库:
git clone https://github.com/dockersamples/linux_tweet_app
确保你有 Docker Hub 的账号 DockerID
任务1: 运行一些简单的docker容器
通过Alpine Linux容器运行单个任务
如果alpine镜像不存在本地,则自动从docker hub中拉取.
$ docker container run alpine hostname
Unable to find image ‘alpine:latest‘ locally
latest: Pulling from library/alpine
aad63a933944: Pull complete
Digest: sha256:b276d875eeed9c7d3f1cfa7edb06b22ed22b14219a7d67c52c56612330348239
Status: Downloaded newer image for alpine:latest
9cbebe6f679d
容器运行hostname
命令输出值: 9cbebe6f679d
只要容器内的进程不退出, 容器会一直保持运行.本例容器运行hostname
指令后退出,但docker不会立即删除容器,而是让容器以Exited
状态存在.
查看所有容器状态:
$ docker container ls -all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9cbebe6f679d alpine "hostname" 5 minutes ago Exited (0) 5 minutes ago zen_elgamal
每个容器都有唯一的ID,本例是 9cbebe6f679d
运行一个任务然后退出的容器非常有用, 例如让容器运行一个脚本, 其他人不需要知道脚本内容和配置信息,只需要执行这个容器.
运行一个交互式的Ubuntu容器
Docker容器的Linux版本不需要与宿主机Linux相同.
运行一个Ubuntu容器,以交互式方式启动
选项说明:
-
-i
/--interactive
: 以交互式运行 -
--tty
: 开启一个虚拟终端 -
--rm
: 退出后删除容器
前两个选项用于开启和docker容器的交互,容器内的shell环境是bash
$ docker container run -i --tty --rm ubuntu bash
Unable to find image ‘ubuntu:latest‘ locally
latest: Pulling from library/ubuntu
5bed26d33875: Pull complete
f11b29a9c730: Pull complete
930bda195c84: Pull complete
78bf9a5ad49e: Pull complete
Digest: sha256:bec5a2727be7fff3d308193cfde3491f8fba1a2ba392b7546b43a051853a341d
Status: Downloaded newer image for ubuntu:latest
root@88681c93701a:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@88681c93701a:/# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.2 0.0 18504 3320 pts/0 Ss 08:27 0:00 bash
root 11 0.0 0.0 34400 2828 pts/0 R+ 08:27 0:00 ps aux
root@88681c93701a:/# cat /etc/issue
Ubuntu 18.04.4 LTS \n \l
root@88681c93701a:/# exit
exit
查看宿主机的版本
$ cat /etc/issue
Welcome to Alpine Linux 3.10
Kernel \r on an \m (\l)
可以看到在Alpine Linux 3.10 系统的机器上允许Ubuntu 18.04.04LTS系统容器.
Linux内核容器需要允许在Linux内核的Docker主机上,Windows内核的容器需要允许在Windows的Docker主机上.
这种交互式的容器运行方式,对于构建镜像之后的检查和验证非常有用,通过这种方式可以将应用构建步骤导出为Dockerfile文件(不建议这么做).通过编写 Dockerfile 文件构建镜像更好(便于版本控制,贡献等)
后台运行的MySQL容器
后台容器是是大多数APP的运行方式.
启动MySQL容器:
$ docker container run --detach --name mydb -e MYSQL_ROOT_PASSWORD=my-secret-pw mysql:latest
Unable to find image ‘mysql:latest‘ locally
latest: Pulling from library/mysql
123275d6e508: Pull complete
27cddf5c7140: Pull complete
c17d442e14c9: Pull complete
5fc78b1e06f8: Pull complete
cd38802f42bb: Pull complete
b370e336f220: Pull complete
f519d6d4d2f6: Pull complete
c52c0310cd34: Pull complete
cd74fd7796ae: Pull complete
3f08e322a29c: Pull complete
2caa0eda62a7: Pull complete
eac28354a6fe: Pull complete
Digest: sha256:7901b65a6be478f7f15348dec0440c491a364af202112c61cb3925d7fb67d8f4
Status: Downloaded newer image for mysql:latest
e52b5d513a22b5b7ca0608b88987fa358fbc0689ca53aa1e14b42750f9638d97
选项说明:
-
--detach
: 使容器在后台运行 -
--name
: 指定容器的别名 -
-e
: 使用环境遍历设置mysql root用户密码(永远不要在生产环境这么做)
查看运行中的容器:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e52b5d513a22 mysql:latest "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 3306/tcp, 33060/tcp mydb
使用两个Docker内建的指令(logs
,top
)查看容器运行情况
#查看输出日志
$ docker container logs mydb
2020-04-17 08:42:01+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian10 started.
2020-04-17 08:42:01+00:00 [Note] [Entrypoint]: Switching to dedicated user ‘mysql‘
2020-04-17 08:42:01+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian10 started.
2020-04-17 08:42:02+00:00 [Note] [Entrypoint]: Initializing database files
2020-04-17T08:42:02.065539Z 0 [Warning] [MY-011070] [Server] ‘Disablingsymbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it‘ is deprecated and will be removed in a future release.
2020-04-17T08:42:02.065651Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.19) initializing of server in progress as process 43
2020-04-17T08:42:04.904103Z 5 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
2020-04-17 08:42:07+00:00 [Note] [Entrypoint]: Database files initialized
2020-04-17 08:42:07+00:00 [Note] [Entrypoint]: Starting temporary server
2020-04-17T08:42:08.178144Z 0 [Warning] [MY-011070] [Server] ‘Disablingsymbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it‘ is deprecated and will be removed in a future release.
2020-04-17T08:42:08.178264Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.19) starting as process 93
2020-04-17T08:42:08.796812Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2020-04-17T08:42:08.798557Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location ‘/var/run/mysqld‘ in the path is accessible to all OS users. Consider choosing a different directory.
2020-04-17T08:42:08.833680Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: ‘8.0.19‘ socket: ‘/var/run/mysqld/mysqld.sock‘ port: 0 MySQL Community Server - GPL.
2020-04-17 08:42:08+00:00 [Note] [Entrypoint]: Temporary server started.
2020-04-17T08:42:08.872465Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: ‘/var/run/mysqld/mysqlx.sock‘
Warning: Unable to load ‘/usr/share/zoneinfo/iso3166.tab‘ as time zone.Skipping it.
Warning: Unable to load ‘/usr/share/zoneinfo/leap-seconds.list‘ as timezone. Skipping it.
Warning: Unable to load ‘/usr/share/zoneinfo/zone.tab‘ as time zone. Skipping it.
Warning: Unable to load ‘/usr/share/zoneinfo/zone1970.tab‘ as time zone. Skipping it.
2020-04-17 08:42:14+00:00 [Note] [Entrypoint]: Stopping temporary server
2020-04-17T08:42:14.401778Z 10 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.19).
2020-04-17T08:42:15.868534Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.19) MySQL Community Server - GPL.
2020-04-17 08:42:16+00:00 [Note] [Entrypoint]: Temporary server stopped
2020-04-17 08:42:16+00:00 [Note] [Entrypoint]: MySQL init process done.Ready for start up.
2020-04-17T08:42:17.023006Z 0 [Warning] [MY-011070] [Server] ‘Disablingsymbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it‘ is deprecated and will be removed in a future release.
2020-04-17T08:42:17.023225Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.19) starting as process 1
2020-04-17T08:42:17.572987Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2020-04-17T08:42:17.575746Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location ‘/var/run/mysqld‘ in the path is accessible to all OS users. Consider choosing a different directory.
2020-04-17T08:42:17.598966Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: ‘8.0.19‘ socket: ‘/var/run/mysqld/mysqld.sock‘ port: 3306 MySQL Community Server - GPL.
2020-04-17T08:42:17.685955Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: ‘/var/run/mysqld/mysqlx.sock‘ bind-address:‘::‘ port: 33060
#查看运行进程
$ docker container top mydb
PID USER TIME COMMAND
22501 999 0:02 mysqld
尽管MySQL正在运行,但是除非显式发布网络端口(端口映射),否则主机流量无法和容器互通.
使用docker container exec
指令传递命令到容器内部执行:
$ docker exec -it mydb mysql --user=root --password=my-scret-pw --version
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql Ver 8.0.19 for Linux on x86_64 (MySQL Community Server - GPL)
或启动一个交互式shell环境后再执行命令
$ docker exec -it mydb sh
# mysql -uroot -p=my-scret-pw --version
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql Ver 8.0.19 for Linux on x86_64 (MySQL Community Server - GPL)
# exit
任务2: 使用Docker打包并运行自定义的APP
了解如何使用Dockerfile文件构建镜像.
本节通过Dockerfile创建一个简单的NGINX Web站点.
构建简单web站点镜像
[node1] (local) root@192.168.0.18 ~
$ cd linux_tweet_app
[node1] (local) root@192.168.0.18 ~/linux_tweet_app
$ cat Dockerfile
FROM nginx:latest
COPY index.html /usr/share/nginx/html
COPY linux.png /usr/share/nginx/html
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
看下Dockerfile的几行命令:
-
FROM
: 指定镜像的基础镜像nginx:latest
-
COPY
: 从Docker主机复制已知位置的文件到镜像 -
EXPOSE
: 说明该镜像使用的端口,文档标识 -
CMD
: 指定从镜像运行容器时的命令和参数
配置下DOCKERID环境变量,然后使用docker image build
构建镜像: -
--tag
: 指定镜像的名称和版本号 -
.
: 表示从当前目录构建.(工作目录)
[node1] (local) root@192.168.0.18 ~/linux_tweet_app
$ export DOCKERID=onion2docker
[node1] (local) root@192.168.0.18 ~/linux_tweet_app
$ echo $DOCKERID
onion2docker
[node1] (local) root@192.168.0.18 ~/linux_tweet_app
$ docker image build --tag $DOCKERID/linux_tweet_app:1.0 .
Sending build context to Docker daemon 110.1kB
Step 1/5 : FROM nginx:latest
latest: Pulling from library/nginx
123275d6e508: Already exists
9a5d769f04f8: Pull complete
faad4f49180d: Pull complete
Digest: sha256:4d947aef8841aed19cc0896a38e12d49d50feba7f583998a164ffeb31e655919
Status: Downloaded newer image for nginx:latest
---> 5a8dfb2ca731
Step 2/5 : COPY index.html /usr/share/nginx/html
---> eb22926b30dd
Step 3/5 : COPY linux.png /usr/share/nginx/html
---> 78953c6d8951
Step 4/5 : EXPOSE 80 443
---> Running in 3041e2761ad1
Removing intermediate container 3041e2761ad1
---> b7bf4ba858b9
Step 5/5 : CMD ["nginx", "-g", "daemon off;"]
---> Running in f451976b0b0d
Removing intermediate container f451976b0b0d
---> da9b6949d169
Successfully built da9b6949d169
Successfully tagged onion2docker/linux_tweet_app:1.0
使用docker container run
运行创建的镜像,为了能访问容器站点,需要使用--publish host_port:container_port
发布端口,这样主机流量就会转发到容器
$ docker container run --detach --publish 80:80 --name linux_tweet_app $DOCKERID/linux_tweet_app:1.0
01442c7d448de9083cae035734577494b6e89d5a91ac08dcf9a4c1a4198020c3
$ curl -is "http://localhost"
HTTP/1.1 200 OK
Server: nginx/1.17.9
Date: Fri, 17 Apr 2020 09:20:34 GMT
Content-Type: text/html
Content-Length: 1595
Last-Modified: Fri, 17 Apr 2020 07:59:22 GMT
Connection: keep-alive
ETag: "5e9961da-63b"
Accept-Ranges: bytes
......
关闭容器:
$ docker container rm --force linux_tweet_app
linux_tweet_app
[node1] (local) root@192.168.0.18 ~/linux_tweet_app
$ docker container ls -al
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e52b5d513a22 mysql:latest "docker-entrypoint.s…" 41 minutes ago Up 41 minutes 3306/tcp, 33060/tcp mydb
rm --force
: 强制终止容器并永久移除容器
在生产环境可以用docker container stop
优雅终止容器,然后使用docker container rm
永久移除
任务3: 修改运行中的web站点
开发阶段, 文件的频繁变更需要反复构建容器, 为此可以使用目录卷将源代码挂在到容器.
使用绑定挂载bind mount可以将主机的文件或目录挂在到在同一主机上运行的容器中.
启动WEB APP容器并挂载本地目录
--mount
:挂载选项
docker container run --detach --publish 80:80 --name linux_tweet_app --mount type=bind,source="$(pwd)",target=/usr/share/nginx/html $DOCKERID/linux_tweet_app:1.0
添加Html文件查看效果
$ echo Hello > hello.html
$ curl http://localhost/hello.html
Hello
注意,虽然修改了本地挂载文件,但是对镜像没有影响
更新镜像
为持久化变更,可以更新版本好后重新构建镜像
$ rm index.html && mv hello.html index.html
$ docker image build --tag $DOCKERID/linux_tweet_app:2.0 .
Sending build context to Docker daemon 111.1kB
Step 1/5 : FROM nginx:latest
---> e791337790a6
Step 2/5 : COPY index.html /usr/share/nginx/html
---> Using cache
---> 9bba0d45248c
Step 3/5 : COPY linux.png /usr/share/nginx/html
---> Using cache
---> 883fb1e0aad3
Step 4/5 : EXPOSE 80 443
---> Using cache
---> fd0d7f3d1eec
Step 5/5 : CMD ["nginx", "-g", "daemon off;"]
---> Using cache
---> a14d46c7844c
Successfully built a14d46c7844c
Successfully tagged onion2docker/linux_tweet_app:2.0
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
onion2docker/linux_tweet_app 1.0 a14d46c7844c 6 minutes ago 127MB
onion2docker/linux_tweet_app 2.0 a14d46c7844c 6 minutes ago 127MB
nginx latest e791337790a6 3 hours ago 127MB
#测试新的镜像
$ docker container run --detach --publish 8080:80 --name linux_tweet_app_2 $DOCKERID/linux_tweet_app:2.0
247d3c34e4c38ac646ac4372226103a981155b5fb8bdaa9dd5e4b10d86e1687c
$ curl http://localhost:8080/
Hello
发布镜像到Docker Hub仓库
#查看本地镜像文件
$ docker image ls -f reference="$DOCKERID/*"
REPOSITORY TAG IMAGE ID CREATED SIZE
onion2docker/linux_tweet_app 3.0 3e44efad81c9 4 minutes ago 127MB
onion2docker/linux_tweet_app 1.0 a14d46c7844c 17 minutes ago 127MB
onion2docker/linux_tweet_app 2.0 a14d46c7844c 17 minutes ago 127MB
#登录Docker Hub
$ docker login
#输入账户密码
...
#推送镜像
$ docker image push $DOCKERID/linux_tweet_app:1.0
The push refers to repository [docker.io/onion2docker/linux_tweet_app]
04b796a00591: Pushed
19a921f8822c: Pushed
be91fceb796e: Mounted from library/nginx
919b6770519b: Mounted from library/nginx
b60e5c3bcef2: Mounted from library/nginx
1.0: digest: sha256:88a0a760eda7e92e956273eba39e74f9ac47730d22e71b38d0e67282424ff3aa size: 1363
$ docker image push $DOCKERID/linux_tweet_app:2.0
The push refers to repository [docker.io/onion2docker/linux_tweet_app]
04b796a00591: Layer already exists
19a921f8822c: Layer already exists
be91fceb796e: Layer already exists
919b6770519b: Layer already exists
b60e5c3bcef2: Layer already exists
2.0: digest: sha256:88a0a760eda7e92e956273eba39e74f9ac47730d22e71b38d0e67282424ff3aa size: 1363