如今 app 开发不再完全是写代码的事了.多语言、多架构、及多环境使得 app 开发流程更加复杂且维护成本变高.
而 Dokcer 可以帮助简化、加速这一开发流程,针对每个项目提供选择工具和维护多种不同开发环境的自由.
本文将探索如何利用 Docker 简化 flutter app 的开发流程.
使用 Docker 的优势
使用 Docker 容器的优势有无数条,这里仅列举几条比较重要的:
- 如果你升级了系统(或者使用朋友的电脑),为了编译 flutter app,你得手动下载所有的相关编译工具.而 docker 就可以跳过手动配置这个过程.只需要从你的 github 下载 Dockerfile 文件(保存了相关编译配置), 然后运行即可.编译、测试、调试 flutter app 只需要等待 Docker 容器下载完成并运行.
- 彻底忘记
它在我电脑上运行的好好的
吧. Dokcer 容器使用了同一份 Dockerfile,在运行时所有的工具将完全一致,无论当前运行的是在哪个云服务平台或操作系统. - Docker 容器因为不需要有独立的操作系统所以非常轻量便携.相对于虚拟机来说,这种架构对资源的需求随依赖的负载而变,且启动快.
- 易伸缩,且不需要在 docker 容器中安装操作系统.不像虚拟机需要申请永久资源.
docker 容器是什么
docker 容器镜像是一个轻量级、独立、包含运行应用一切所需(代码、运行时、系统工具、系统库及相关配置)的可执行软件包集合.当它运行在 docker 引擎上时就变成了一个 docker 容器.
查看 更多关于 docker 容器的知识和容器与虚拟机的区别
配置 docker
首先下载对应操作系统的 docker 引擎.
注意: 在 Windows 上使用 Docker 需要在 BIOS 开启硬件加速虚拟化技术.查看 StackOverflow 上的相关讨论.
安装完后先确认 docker 是否可以正常运行(macOS 和 linux 使用终端, Windows 使用 PowerShell).
docker --version
复制代码
然后会显示当前操作系统安装的 docker 版本号
Docker version 19.03.8, build afacb8b
复制代码
可以通过下面命令测试 docker(会从 DokcerHub 下载 hello-world 镜像)
docker run hello-world
复制代码
如果是第一次运行会显示如下结果
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:ca0eeb6fb05351dfc8759c20733c91def84cb8007aa89a5bf606bc8b315b9fc7
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
复制代码
如果是 linux 用户,为了在 VS Code 环境中使用需要给予 root 权限.创建 docker 组添加用户.
如下所示:
1、创建 docker 组
sudo groupadd docker
复制代码
2、向 docker 组添加用户
sudo usermod -aG docker $USER
复制代码
3、linux 环境下,运行如下命令激活组
newgrp docker
复制代码
4、验证是否无 sudo 可以运行 docker 命令
docker run hello-world
复制代码
linux 安装后操作查看官方指南
配置 VS Code
接下来将从 VS Code 环境中访问 docker 容器,这样就可在 VS Code 中直接访问 flutter 目录.这将简化 flutter 开发流程
- 下载 VS Code
- 下载并安装两个 VS Code 插件
创建 docker 容器
1、创建 flutter_docker 目录
mkdir flutter_docker
复制代码
2、 使用 VS Code 打开此目录
code flutter_docker
复制代码
3、新建 Dockerfile
文件
4、向 Dockerfile
添加如下内容
FROM ubuntu:18.04
# 前置要求
RUN apt update && apt install -y curl git unzip xz-utils zip libglu1-mesa openjdk-8-jdk wget
# 设置新用户
RUN useradd -ms /bin/bash developer
USER developer
WORKDIR /home/developer
# 准备安卓目录和系统变量
RUN mkdir -p Android/sdk
ENV ANDROID_SDK_ROOT /home/developer/Android/sdk
RUN mkdir -p .android && touch .android/repositories.cfg
# 设置安卓 SDK
RUN get -O sdk-tools.zip https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
RUN unzip sdk-tools.zip && rm sdk-tools.zip
RUN mv tools Android/sdk/tools
RUN cd Android/sdk/tools/bin && yes | ./sdkmanager --lincenses
RUN cd Android/sdk/tools/bin && ./sdkmanager "build-tools;29.0.2" "sources;android-29"
ENV PATH "$PATH:/home/deveoper/Android/sdk/platform-tools"
# 下载 flutter SDK
RUN git clone https://github.com/flutter/flutter.git
ENV PATH "$PATH:/home/developer/flutter/bin"
# 检测 flutter
RUN flutter doctor
复制代码
5、创建 .devcontainer
文件夹,并在其中新建 devcontainer.json
文件
6、为 devcontainer.json
添加如下内容:
{
"name": "flutter_docker",
"context": ".",
"dockerFile": "../Dockerfile",
"remoteUser": "developer",
"mounts": [
"source=/dev/bus/usb,target=/dev/bus/usb,type=bind"
],
"settings": {
"terminal.integrated.shell.linux"
: null
},
"runArgs": ["--privileged"],
"extensions": ["dart-core.flutter"],
"workspaceMount": "source=${localWorkspaceFolder}/workspace,target=/home/developer/workspace,type=bind,consistency=delegated",
"workspaceFolder":"/home/developer/workspace"
}
复制代码
重要提醒: macOS 和 Windows 的用户无法通过
mounts
属性访问 USB 端口.不要在devcontainer.json
中定义这个属性,否则会导致 docker 容器构建失败.更多内容后面会介绍.
7、在根目录下添加 workspace
文件夹.此文件夹将用来存储 flutter 项目在 docker 容器内部创建的内容.
现在就可以在 VS Code 环境中构建运行容器.在这之前,先来了解下 Dockerfile
和 devcontainer.json
.
当然可以使用官方团队维护的 flutter docker 镜像, 比如cirrusci/flutter
了解 Dockerfile
Dockerfile 是一个包含了用户在命令行打包镜像时用到的命令的文本文件.docker 可以通过读取 Dockerfile 文件指令自动构建镜像.
这个构建过程是由 Docker 守护进程实现的,不是 CLI.
我们定义的 Dokcerfile 将下载和安装开发 flutter apps 需要的所有必要工具.
1、FROM
: 从ubuntu:18.04
docker 镜像中创建新的层.
2、在使用RUN
命令之前,所有必要的包都是通过apt
下载安装的.
curl git unzip xz-utils zip libglu2-mesa
flutter SDK 依赖openjdk-8-jdk
Android SDK 依赖wget
用来下载某些Android tools
3、添加非 root 用户 developer,设为当前用户,改变当前工作文件夹到 home 目录下
RUN useradd -ms /bin/bash developer
USER developer
WORKDIR /home/developer
复制代码
4、创建 Android SDK 安装目录.设置 ANDROID_SDK_ROOT
环境变量, flutter 会用到
RUN mkdir -p Android/sdk
ENV ANDROID_SDK_ROOT /home/developer/Android/sdk
RUN mkdir -p .android && touch .android/repositories.cfg
复制代码
5、下载最新的 SDK 工具.解压然后移动到正确的文件夹下.然后使用 sdkmanager
接受 Android License
并下载.最后添加 adb
路径.
此处我特别指定了 API29,如果想使用其他 Android 版本,也可以指定其他.
RUN wget -O sdk-tools.zip https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
RUN unzip sdk-tools.zip && rm sdk-tools.zip
RUN mv tools Android/sdk/tools
RUN cd Android/sdk/tools/bin && yes | ./sdkmanager --licenses
RUN cd Android/sdk/tools/bin && ./sdkmanager "build-tools;29.0.2" "patcher;v4" "platform-tools" "platforms;android-29" "sources;android-29"
ENV PATH "$PATH:/home/developer/Android/sdk/platform-tools"
复制代码
6、从 github 仓库克隆 Flutter, 为 flutter 命令添加 PATH 环境变量.
RUN git clone https://github.com/flutter/flutter.git
ENV PATH "$PATH:/home/developer/flutter/bin"
复制代码
7、最后运行flutter doctor
命令下载 Dart SDK 来检查 flutter 是否配置正确.
RUN flutter doctor
复制代码
了解 devcontainer.json
devcontainer.json
告诉 VS Code 如何访问(或创建)一个定义好的工具和运行时栈的开发环境.
访问这里获取更多信息
我们在 devcontainer.json
中使用到的属性如下所述:
- name: 容器的名称
- context: docker 相对于
devcontainer.json
文件构建的工作目录. - dockerFile: Dockerfile 的位置,相对于
devcontainer.json
文件来说. - remoteUser: 将在容器中使用的用户名
- mounts: 在容器运行时被添加到的挂载点数组.此处我们把
/dev/bus/usb
挂载,以便容器能探测到任何安卓设备链接到系统(macOS 和 Windows 不可用) - settings: 向容器/机器指定的设置文件添加
settings.json
值. - runArgs: 有效的 docker 参数,string 数组. 使用
--privigleged
可以确保容器能访问链接到系统的设备. - extensions: 指定当容器创建时应该安装的扩展 ID 数组.
dart-code.flutter
是 flutter 开发的官方扩展。 - workspaceMount: 覆盖本地默认的挂载工作空间
- workspaceFolder: 当链接到容器时 VS Code 应该打开的默认路径.
更多
devcontianer.json
属性查看这里
构建运行 docker 容器
如果已经为 VS Code 安装过 Remote Development
插件, 那么在 VS Code 窗口的左下角会看到显示的图标.
1、点击此图标
2、选择弹出来的选项: Remote-Containers: Open Folder in Container
3、选择包含 Dockerfile(还有其他设置) 容器的根目录打开开始构建 docker 容器.这需要一点时间,因为它需要下载并为此容器配置所有工具.
构建完成后,将会自动打开 docker 容器的 bash 终端
.
开始开发
首先运行 flutter doctor
验证所有配置是否正确.
可能会看到在 Android Studio 和 Connected device 旁边有黄色的警示.
Android Studio 的警示是因为我们未安装 flutter 和 dart 插件.因为我们用 VS Code 开发,所以可以忽略.
Connected device 警示是因为我们没有连接设备.
重要提示: 下面的步骤仅适用于用户可以通过 USB 端口访问安卓设备的 Linux 操作系统.如果是 macOS 或 Windows,那么可以跳过.
现在通过 USB 端口连接安卓设备.
在手机上设置 PTP
或 文件传输
连接模式.
接下来再运行就不会看到黄色警示了.
如果没有看到绿色对号,那么可能是当前系统
adb
的问题,adb
一定得连接上.运行在手机上的ADB 守护进程
是无法同时连接两个ADB server
的.所以在当前系统运行如下命令断开 ADB 连接adb kill-server
现在应该可以通过 docker 里的 adb 连接上设备了.
使用 flutter create demo
创建 flutter 项目.
在 workspace 目录下将会创建 demo 项目.
进入此目录然后运行
cd demo
flutter run
复制代码
此时就会从 docker 容器中直接在连接的手机运行 flutter app.
macOS 和 Windows 开发者
macOS 和 Windows 开发者无法在 docker 容器通过 USB 端口访问手机.所以只有通过 TCP/IP 和手机建立无线连接才能访问.
首先得在操作系统安装 adb
.adb 在 Android SDK platform-tools
目录下,记得设置 PATH 变量,然后连接手机,开启调试模式.
1、列出当前连接的设备
adb devices
复制代码
2、开启无线连接
adb tcpip 555
adb connect 192.168.0.5:5555
adb devices
复制代码
此处把 IP 地址替换为连接手机的 wifi 地址. 注意: 手机和电脑得处在同一局域网下.
3、断开手机的 USB 连接,然后再运行 adb devices
验证此设备是否仍然连接.
4、在 VS Code 运行 docker 容器
5、在容器里的终端运行 adb devices
验证设备是否可访问.
此时会返回空列表
6、执行如下命令
adb connect 192.168.0.5:5555
adb devices
复制代码
此处的 IP 和端口应和链接到电脑的一致. 同时确保打开手机弹出的
允许 USB 调试
窗口
7、如果出现 unauthorized,那么按如下操作
adb kill-server
adb connect 192.168.0.5:5555
adb devices
复制代码
这样 unauthorized 就会消失了.
8、flutter doctor
结论
docker 可以帮助简化 flutter 应用开发流程,保证开发过程一致。