背景
突然看到电脑上安装的Docker,一直以来都只是装上了却没有用过,遂启动了提供的docker/getting-started项目,按照这个项目中的教程看了看。
—— 因此本文内容均来自官方教程,主要是对相关内容进行了提炼。
拉镜像
docker run -d -p 80:80 docker/getting-started
执行命令后,将会拉下来一个Docker镜像,并实例化一个容器。这里将容器的80端口暴露给了主机80的端口,通过主机访问 http://localhost 即可进入这个教程页面。
创建自己的镜像
打开教程提供的前端项目,在前端项目工作目录根文件夹创建一个名为Dockerfile的文件
FROM node:12-alpine
RUN apk add --no-cache python g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
然后执行
docker build -t getting-started .
这里相当于以node:12-alpine镜像作为基础,创建一个包含node以及alpine的容器,同时会在容器中安装python、 g++、make;接下来似乎会在容器中的根目录下创建一个app根目录并切换到这个文件夹,如何会把主机上当前工作目录中的内容拷贝到其中,之后的步骤将会为工作目录中的前端项目安装依赖,并启动项目 —— 这里步骤和正常的前端项目一致,区别在于这一步是发生在容器当中的。
执行结束后,将会以当前容器为基础,创建好一个镜像。
启动容器
上一步的镜像创建好以后,执行
docker run -dp 3000:3000 getting-started
即可创建并启动一个容器。同样这里把容器的3000端口暴露到了主机的3000端口,通过主机访问 http://localhost:3000 即可进入一个todo示例应用的页面 —— 这里就相当于已经把应用给部署好了。
升级应用
当应用程序的源代码发生变化后,自然需要来更新一下容器中正在运行的项目。此时若执行
docker build -t getting-started .
docker run -dp 3000:3000 getting-started
将会导致报错 —— 因为上一步中创建的容器仍然在运行。这时我们需要停止、删除旧容器,然后才能为升级后的应用创建新容器,以替代旧应用。
可通过
获得所有人容器列表,找到旧容器,借助
docker stop <the-container-id>
来停止旧容器,通过
docker rm <the-container-id>
再删除旧容器。
再执行
docker run -dp 3000:3000 getting-started
来启动新应用。
保持旧应用中的数据以在新应用中使用
旧应用的容器删除后,其中的数据也将一并删除。那是否有办法保持数据呢?Docker提供了存储卷(Volume)来解决这个问题。存储卷独立于容器而存在,且可以被多个容器共享使用。存储卷可被挂载到容器的文件夹中。
通过
docker volume create todo-db
即创建了一个名为todo-db的存储卷。
可通过
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
来将todo-db存储卷挂在到容器内/etc/todos文件夹下。当对/etc/todos中的内容进行操作时,即在操作todo-db存储卷中的内容。
在容器中开发项目
将主机中的真实目录挂载到容器中,并在容器中进行开发。
执行
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
getting-started \
sh -c "yarn install && yarn run dev"
这里同样将3000端口暴露到了主机的3000端口,将主机的$(pwd):/app挂载到容器中的/app目录下,并和日常开发一样执行yarn install && yarn run dev即可进入应用的开发模式。
可以通过
docker logs -f <container-id>
来查看控制台输出。
多容器交互
上面示例我们只用到了一个单独的容器。有时我们的应用想要跑起来,可能会依赖多个模块,而这些模块又分别由不同容器提供。例如后端服务由Node.js提供,数据库由MySQL提供。在Docker下,每个容器之间是隔离的。若要让容器与容器之间产生联系,可以将这些容器接入同一网络,以实现互相访问。
要创建网络,可以执行
docker network create todo-app
这就创建了一个名为todo-app的网络。
接下来我们可以基于MySQL镜像创建一个容器,同时让这个容器接入todo-app网络
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 \
-p 3306:3306 \
ibex/debian-mysql-server-5.7
这一步基于MySQL镜像创建了一个容器,同时也指定了MySQL的数据是存入todo-mysql-data存储卷里的 —— 虽然这里没有显式指明要创建一个存储卷,但Docker帮我们创建了;这里使用环境变量指定了数据库的一些信息;接下来指定了暴露给主机的端口。
MySQL官方镜像是mysql:5.7,不过笔者使用的是基于ARM的处理器,官方镜像不支持基于ARM的处理器,因此使用了其他开发者贡献的支持基于ARM处理器的镜像ibex/debian-mysql-server-5.7
MySQL容器创建后,可以通过
docker exec -it <mysql-container-id> mysql -p
执行语句
检查数据库是否创建成功
下面就可以把我们的应用与MySQL进行连接了。
执行
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 \
getting-started \
sh -c "yarn install && yarn run dev"
就使得托管应用的服务器与MySQL在同一网络(todo-app)下。此时如果在页面上触发能让MySQL数据库发生变化的操作,MySQL中对应表中的内容也将会发生变化。
小坑
我们的应用在连接数据库时可能会出现Host '172.21.0.3' is not allowed to connect to this MySQL server这样的提示,即应用无权连接到数据库。这时我们需要进入运行数据库的容器,来调整一下允许用户登录的Host - 默认Host为localhost,即只允许用户在本地登录。
首先进入容器并登陆MySQL
docker exec -it <mysql-container-id> mysql -p
执行
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'secret' WITH GRANT OPTION;
FLUSH PRIVILEGES;
来让root用户可以通过任意Host进行登录。
背景
突然看到电脑上安装的Docker,一直以来都只是装上了却没有用过,遂启动了提供的
docker/getting-started项目,按照这个项目中的教程看了看。—— 因此本文内容均来自官方教程,主要是对相关内容进行了提炼。
拉镜像
执行命令后,将会拉下来一个Docker镜像,并实例化一个容器。这里将容器的80端口暴露给了主机80的端口,通过主机访问 http://localhost 即可进入这个教程页面。
创建自己的镜像
打开教程提供的前端项目,在前端项目工作目录根文件夹创建一个名为
Dockerfile的文件然后执行
docker build -t getting-started .这里相当于以
node:12-alpine镜像作为基础,创建一个包含node以及alpine的容器,同时会在容器中安装python、g++、make;接下来似乎会在容器中的根目录下创建一个app根目录并切换到这个文件夹,如何会把主机上当前工作目录中的内容拷贝到其中,之后的步骤将会为工作目录中的前端项目安装依赖,并启动项目 —— 这里步骤和正常的前端项目一致,区别在于这一步是发生在容器当中的。执行结束后,将会以当前容器为基础,创建好一个镜像。
启动容器
上一步的镜像创建好以后,执行
即可创建并启动一个容器。同样这里把容器的3000端口暴露到了主机的3000端口,通过主机访问 http://localhost:3000 即可进入一个todo示例应用的页面 —— 这里就相当于已经把应用给部署好了。
升级应用
当应用程序的源代码发生变化后,自然需要来更新一下容器中正在运行的项目。此时若执行
docker build -t getting-started . docker run -dp 3000:3000 getting-started将会导致报错 —— 因为上一步中创建的容器仍然在运行。这时我们需要停止、删除旧容器,然后才能为升级后的应用创建新容器,以替代旧应用。
可通过
获得所有人容器列表,找到旧容器,借助
来停止旧容器,通过
再删除旧容器。
再执行
来启动新应用。
保持旧应用中的数据以在新应用中使用
旧应用的容器删除后,其中的数据也将一并删除。那是否有办法保持数据呢?Docker提供了存储卷(Volume)来解决这个问题。存储卷独立于容器而存在,且可以被多个容器共享使用。存储卷可被挂载到容器的文件夹中。
通过
即创建了一个名为
todo-db的存储卷。可通过
来将
todo-db存储卷挂在到容器内/etc/todos文件夹下。当对/etc/todos中的内容进行操作时,即在操作todo-db存储卷中的内容。在容器中开发项目
将主机中的真实目录挂载到容器中,并在容器中进行开发。
执行
docker run -dp 3000:3000 \ -w /app -v "$(pwd):/app" \ getting-started \ sh -c "yarn install && yarn run dev"这里同样将3000端口暴露到了主机的3000端口,将主机的
$(pwd):/app挂载到容器中的/app目录下,并和日常开发一样执行yarn install && yarn run dev即可进入应用的开发模式。可以通过
来查看控制台输出。
多容器交互
上面示例我们只用到了一个单独的容器。有时我们的应用想要跑起来,可能会依赖多个模块,而这些模块又分别由不同容器提供。例如后端服务由Node.js提供,数据库由MySQL提供。在Docker下,每个容器之间是隔离的。若要让容器与容器之间产生联系,可以将这些容器接入同一网络,以实现互相访问。
要创建网络,可以执行
这就创建了一个名为
todo-app的网络。接下来我们可以基于MySQL镜像创建一个容器,同时让这个容器接入
todo-app网络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 \ -p 3306:3306 \ ibex/debian-mysql-server-5.7这一步基于MySQL镜像创建了一个容器,同时也指定了MySQL的数据是存入
todo-mysql-data存储卷里的 —— 虽然这里没有显式指明要创建一个存储卷,但Docker帮我们创建了;这里使用环境变量指定了数据库的一些信息;接下来指定了暴露给主机的端口。MySQL容器创建后,可以通过
执行语句
检查数据库是否创建成功
下面就可以把我们的应用与MySQL进行连接了。
执行
就使得托管应用的服务器与MySQL在同一网络(todo-app)下。此时如果在页面上触发能让MySQL数据库发生变化的操作,MySQL中对应表中的内容也将会发生变化。