1*c8dee2aaSAndroid Build Coastguard Worker"""This module defines the skia_app_container macro.""" 2*c8dee2aaSAndroid Build Coastguard Worker 3*c8dee2aaSAndroid Build Coastguard Workerload("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_push") 4*c8dee2aaSAndroid Build Coastguard Workerload("@io_bazel_rules_docker//docker/util:run.bzl", "container_run_and_commit") 5*c8dee2aaSAndroid Build Coastguard Workerload("@rules_pkg//:pkg.bzl", "pkg_tar") 6*c8dee2aaSAndroid Build Coastguard Worker 7*c8dee2aaSAndroid Build Coastguard Workerdef skia_app_container( 8*c8dee2aaSAndroid Build Coastguard Worker name, 9*c8dee2aaSAndroid Build Coastguard Worker repository, 10*c8dee2aaSAndroid Build Coastguard Worker dirs, 11*c8dee2aaSAndroid Build Coastguard Worker entrypoint = "", 12*c8dee2aaSAndroid Build Coastguard Worker run_commands_root = None, 13*c8dee2aaSAndroid Build Coastguard Worker run_commands_skia = None, 14*c8dee2aaSAndroid Build Coastguard Worker base_image = "@basealpine//image", 15*c8dee2aaSAndroid Build Coastguard Worker env = None, 16*c8dee2aaSAndroid Build Coastguard Worker default_user = "skia"): 17*c8dee2aaSAndroid Build Coastguard Worker """Builds a Docker container for a Skia app, and generates a target to push it to GCR. 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker This macro produces the following: 20*c8dee2aaSAndroid Build Coastguard Worker * "<name>" target to build the Docker container with skia as default user. 21*c8dee2aaSAndroid Build Coastguard Worker * "<name>_run_root" target to execute run commands as root on the image. 22*c8dee2aaSAndroid Build Coastguard Worker root will be the default user here. Will be created only 23*c8dee2aaSAndroid Build Coastguard Worker if run_commands_root is specified. 24*c8dee2aaSAndroid Build Coastguard Worker * "<name>_run_skia" target to execute run commands as the "skia" user on the image. 25*c8dee2aaSAndroid Build Coastguard Worker Will be created only if run_commands_skia is specified. 26*c8dee2aaSAndroid Build Coastguard Worker * "push_<name>" target to push the container to GCR. 27*c8dee2aaSAndroid Build Coastguard Worker 28*c8dee2aaSAndroid Build Coastguard Worker Example: 29*c8dee2aaSAndroid Build Coastguard Worker 30*c8dee2aaSAndroid Build Coastguard Worker ``` 31*c8dee2aaSAndroid Build Coastguard Worker # //myapp/BUILD.bazel 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker load("//bazel:skia_app_container.bzl", "skia_app_container") 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker skia_app_container( 36*c8dee2aaSAndroid Build Coastguard Worker name = "myapp", 37*c8dee2aaSAndroid Build Coastguard Worker dirs = { 38*c8dee2aaSAndroid Build Coastguard Worker "/usr/local/bin/myapp": [ 39*c8dee2aaSAndroid Build Coastguard Worker ["//myapp/go:mybinary", 755"], 40*c8dee2aaSAndroid Build Coastguard Worker ], 41*c8dee2aaSAndroid Build Coastguard Worker "/usr/local/share/myapp": [ 42*c8dee2aaSAndroid Build Coastguard Worker ["//myapp/config:config.cfg", "644"], 43*c8dee2aaSAndroid Build Coastguard Worker ["//myapp/data:data.json", "644"], 44*c8dee2aaSAndroid Build Coastguard Worker ], 45*c8dee2aaSAndroid Build Coastguard Worker }, 46*c8dee2aaSAndroid Build Coastguard Worker entrypoint = "/usr/local/bin/myapp/mybinary", 47*c8dee2aaSAndroid Build Coastguard Worker repository = "skia-public/myapp", 48*c8dee2aaSAndroid Build Coastguard Worker ) 49*c8dee2aaSAndroid Build Coastguard Worker ``` 50*c8dee2aaSAndroid Build Coastguard Worker 51*c8dee2aaSAndroid Build Coastguard Worker The above example will produce a Docker container based on gcr.io/skia-public/basealpine with 52*c8dee2aaSAndroid Build Coastguard Worker the following contents: 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker - /usr/local/bin/myapp/mybinary (mode: 755) 55*c8dee2aaSAndroid Build Coastguard Worker - /usr/local/share/myapp/config.cfg (mode: 644) 56*c8dee2aaSAndroid Build Coastguard Worker - /usr/local/share/myapp/data.json (mode: 644) 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Worker To build the container and load it into Docker: 59*c8dee2aaSAndroid Build Coastguard Worker 60*c8dee2aaSAndroid Build Coastguard Worker ``` 61*c8dee2aaSAndroid Build Coastguard Worker $ bazel run //myapp:myapp 62*c8dee2aaSAndroid Build Coastguard Worker ... 63*c8dee2aaSAndroid Build Coastguard Worker Loaded image ID: sha256:c0decafe 64*c8dee2aaSAndroid Build Coastguard Worker Tagging c0decafe as bazel/myapp:myapp 65*c8dee2aaSAndroid Build Coastguard Worker ``` 66*c8dee2aaSAndroid Build Coastguard Worker 67*c8dee2aaSAndroid Build Coastguard Worker To debug the container locally: 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Worker ``` 70*c8dee2aaSAndroid Build Coastguard Worker $ docker run bazel/myapp:myapp 71*c8dee2aaSAndroid Build Coastguard Worker $ docker run -it --entrypoint /bin/sh bazel/myapp:myapp 72*c8dee2aaSAndroid Build Coastguard Worker ``` 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Worker To push the container to GCR: 75*c8dee2aaSAndroid Build Coastguard Worker 76*c8dee2aaSAndroid Build Coastguard Worker ``` 77*c8dee2aaSAndroid Build Coastguard Worker $ bazel run //myapp:push_myapp 78*c8dee2aaSAndroid Build Coastguard Worker ... 79*c8dee2aaSAndroid Build Coastguard Worker Successfully pushed Docker image to gcr.io/skia-public/myapp:... 80*c8dee2aaSAndroid Build Coastguard Worker ``` 81*c8dee2aaSAndroid Build Coastguard Worker 82*c8dee2aaSAndroid Build Coastguard Worker Args: 83*c8dee2aaSAndroid Build Coastguard Worker name: Name of the rule. 84*c8dee2aaSAndroid Build Coastguard Worker repository: Name of the repository under gcr.io. 85*c8dee2aaSAndroid Build Coastguard Worker dirs: Contents of the container, expressed as a dictionary where the keys are directory names 86*c8dee2aaSAndroid Build Coastguard Worker within the container (e.g. "/usr/local/share/myapp"), and the values are an array of 87*c8dee2aaSAndroid Build Coastguard Worker [Bazel label, mode] tuples indicating which files should be copied into the directory (e.g. 88*c8dee2aaSAndroid Build Coastguard Worker ["//myapp/go:mybinary", "755"]). 89*c8dee2aaSAndroid Build Coastguard Worker entrypoint: The entrypoint of the container, which can be a string or an array (e.g. 90*c8dee2aaSAndroid Build Coastguard Worker "/usr/local/share/myapp/mybinary", or ["/usr/local/share/myapp/mybinary", "--someflag"]). 91*c8dee2aaSAndroid Build Coastguard Worker Optional. 92*c8dee2aaSAndroid Build Coastguard Worker run_commands_root: The RUN commands that should be executed on the container by the root 93*c8dee2aaSAndroid Build Coastguard Worker user. Optional. 94*c8dee2aaSAndroid Build Coastguard Worker run_commands_skia: The RUN commands that should be executed on the container by the skia 95*c8dee2aaSAndroid Build Coastguard Worker user. Optional. 96*c8dee2aaSAndroid Build Coastguard Worker base_image: The image to base the container_image on. Optional. 97*c8dee2aaSAndroid Build Coastguard Worker env: A {"var": "val"} dictionary with the environment variables to use when building the 98*c8dee2aaSAndroid Build Coastguard Worker container. Optional. 99*c8dee2aaSAndroid Build Coastguard Worker default_user: The user the container will be run with. Defaults to "skia" but some apps 100*c8dee2aaSAndroid Build Coastguard Worker like skfe requires the default user to be "root". 101*c8dee2aaSAndroid Build Coastguard Worker """ 102*c8dee2aaSAndroid Build Coastguard Worker 103*c8dee2aaSAndroid Build Coastguard Worker # According to the container_image rule's docs[1], the recommended way to place files in 104*c8dee2aaSAndroid Build Coastguard Worker # specific directories is via the pkg_tar rule. 105*c8dee2aaSAndroid Build Coastguard Worker # 106*c8dee2aaSAndroid Build Coastguard Worker # The below loop creates one pkg_tar rule for each file in the container. 107*c8dee2aaSAndroid Build Coastguard Worker # 108*c8dee2aaSAndroid Build Coastguard Worker # [1] https://github.com/bazelbuild/rules_docker/blob/454981e65fa100d37b19210ee85fedb2f7af9626/README.md#container_image 109*c8dee2aaSAndroid Build Coastguard Worker pkg_tars = [] 110*c8dee2aaSAndroid Build Coastguard Worker i = 0 111*c8dee2aaSAndroid Build Coastguard Worker for dir in dirs: 112*c8dee2aaSAndroid Build Coastguard Worker for file, mode in dirs[dir]: 113*c8dee2aaSAndroid Build Coastguard Worker pkg_tar_name = name + "_pkg_tar_" + str(i) 114*c8dee2aaSAndroid Build Coastguard Worker i += 1 115*c8dee2aaSAndroid Build Coastguard Worker pkg_tars.append(pkg_tar_name) 116*c8dee2aaSAndroid Build Coastguard Worker 117*c8dee2aaSAndroid Build Coastguard Worker pkg_tar( 118*c8dee2aaSAndroid Build Coastguard Worker name = pkg_tar_name, 119*c8dee2aaSAndroid Build Coastguard Worker srcs = [file], 120*c8dee2aaSAndroid Build Coastguard Worker package_dir = dir, 121*c8dee2aaSAndroid Build Coastguard Worker mode = mode, 122*c8dee2aaSAndroid Build Coastguard Worker tags = ["manual"], # Exclude it from wildcard queries, e.g. "bazel build //...". 123*c8dee2aaSAndroid Build Coastguard Worker ) 124*c8dee2aaSAndroid Build Coastguard Worker 125*c8dee2aaSAndroid Build Coastguard Worker image_name = (name + "_base") if (run_commands_root or run_commands_skia) else name 126*c8dee2aaSAndroid Build Coastguard Worker 127*c8dee2aaSAndroid Build Coastguard Worker container_image( 128*c8dee2aaSAndroid Build Coastguard Worker name = image_name, 129*c8dee2aaSAndroid Build Coastguard Worker base = base_image, 130*c8dee2aaSAndroid Build Coastguard Worker 131*c8dee2aaSAndroid Build Coastguard Worker # We cannot use an entrypoint with the container_run_and_commit rule 132*c8dee2aaSAndroid Build Coastguard Worker # required when run_commands_root or run_commands_skia is specified, 133*c8dee2aaSAndroid Build Coastguard Worker # because the commands we want to execute do not require a specific 134*c8dee2aaSAndroid Build Coastguard Worker # entrypoint. 135*c8dee2aaSAndroid Build Coastguard Worker # We will set the entrypoint back after the container_run_and_commit 136*c8dee2aaSAndroid Build Coastguard Worker # rule is executed. 137*c8dee2aaSAndroid Build Coastguard Worker entrypoint = None if (run_commands_root or run_commands_skia) else [entrypoint], 138*c8dee2aaSAndroid Build Coastguard Worker tars = pkg_tars, 139*c8dee2aaSAndroid Build Coastguard Worker user = default_user, 140*c8dee2aaSAndroid Build Coastguard Worker tags = ["manual"], # Exclude it from wildcard queries, e.g. "bazel build //...". 141*c8dee2aaSAndroid Build Coastguard Worker env = env, 142*c8dee2aaSAndroid Build Coastguard Worker ) 143*c8dee2aaSAndroid Build Coastguard Worker 144*c8dee2aaSAndroid Build Coastguard Worker if run_commands_root: 145*c8dee2aaSAndroid Build Coastguard Worker rule_name = name + "_run_root" 146*c8dee2aaSAndroid Build Coastguard Worker container_run_and_commit( 147*c8dee2aaSAndroid Build Coastguard Worker name = rule_name, 148*c8dee2aaSAndroid Build Coastguard Worker commands = run_commands_root, 149*c8dee2aaSAndroid Build Coastguard Worker docker_run_flags = ["--user", "root"], 150*c8dee2aaSAndroid Build Coastguard Worker image = image_name + ".tar", 151*c8dee2aaSAndroid Build Coastguard Worker tags = [ 152*c8dee2aaSAndroid Build Coastguard Worker "manual", # Exclude it from wildcard queries, e.g. "bazel build //...". 153*c8dee2aaSAndroid Build Coastguard Worker # container_run_and_commit requires the docker daemon to be 154*c8dee2aaSAndroid Build Coastguard Worker # running. This is not possible inside RBE. 155*c8dee2aaSAndroid Build Coastguard Worker "no-remote", 156*c8dee2aaSAndroid Build Coastguard Worker ], 157*c8dee2aaSAndroid Build Coastguard Worker ) 158*c8dee2aaSAndroid Build Coastguard Worker image_name = ":" + rule_name + "_commit.tar" 159*c8dee2aaSAndroid Build Coastguard Worker 160*c8dee2aaSAndroid Build Coastguard Worker if run_commands_skia: 161*c8dee2aaSAndroid Build Coastguard Worker rule_name = name + "_run_skia" 162*c8dee2aaSAndroid Build Coastguard Worker container_run_and_commit( 163*c8dee2aaSAndroid Build Coastguard Worker name = rule_name, 164*c8dee2aaSAndroid Build Coastguard Worker commands = run_commands_skia, 165*c8dee2aaSAndroid Build Coastguard Worker docker_run_flags = ["--user", "skia"], 166*c8dee2aaSAndroid Build Coastguard Worker # If run_commands_root was specified then the image_name already contains 167*c8dee2aaSAndroid Build Coastguard Worker # ".tar" suffix. Make sure we do not add a double ".tar" suffix here. 168*c8dee2aaSAndroid Build Coastguard Worker image = image_name if image_name.endswith(".tar") else image_name + ".tar", 169*c8dee2aaSAndroid Build Coastguard Worker tags = [ 170*c8dee2aaSAndroid Build Coastguard Worker "manual", # Exclude it from wildcard queries, e.g. "bazel build //...". 171*c8dee2aaSAndroid Build Coastguard Worker # container_run_and_commit requires the docker daemon to be 172*c8dee2aaSAndroid Build Coastguard Worker # running. This is not possible inside RBE. 173*c8dee2aaSAndroid Build Coastguard Worker "no-remote", 174*c8dee2aaSAndroid Build Coastguard Worker ], 175*c8dee2aaSAndroid Build Coastguard Worker ) 176*c8dee2aaSAndroid Build Coastguard Worker image_name = ":" + rule_name + "_commit.tar" 177*c8dee2aaSAndroid Build Coastguard Worker 178*c8dee2aaSAndroid Build Coastguard Worker if run_commands_root or run_commands_skia: 179*c8dee2aaSAndroid Build Coastguard Worker # If run_commands_root was specified then it's container_run_and_commit 180*c8dee2aaSAndroid Build Coastguard Worker # sets root as the default user and overrides the entrypoint. 181*c8dee2aaSAndroid Build Coastguard Worker # If run_commands_skia was specified then it overrides the entrypoint. 182*c8dee2aaSAndroid Build Coastguard Worker # 183*c8dee2aaSAndroid Build Coastguard Worker # Now execute container_image using the previous image as base to set 184*c8dee2aaSAndroid Build Coastguard Worker # back skia as the default user and to set back the original entrypoint. 185*c8dee2aaSAndroid Build Coastguard Worker rule_name = name 186*c8dee2aaSAndroid Build Coastguard Worker container_image( 187*c8dee2aaSAndroid Build Coastguard Worker name = rule_name, 188*c8dee2aaSAndroid Build Coastguard Worker base = image_name, 189*c8dee2aaSAndroid Build Coastguard Worker entrypoint = [entrypoint], 190*c8dee2aaSAndroid Build Coastguard Worker user = default_user, 191*c8dee2aaSAndroid Build Coastguard Worker tags = ["manual"], # Exclude it from wildcard queries, e.g. "bazel build //...". 192*c8dee2aaSAndroid Build Coastguard Worker env = env, 193*c8dee2aaSAndroid Build Coastguard Worker ) 194*c8dee2aaSAndroid Build Coastguard Worker image_name = ":" + rule_name 195*c8dee2aaSAndroid Build Coastguard Worker 196*c8dee2aaSAndroid Build Coastguard Worker container_push( 197*c8dee2aaSAndroid Build Coastguard Worker name = "push_" + name, 198*c8dee2aaSAndroid Build Coastguard Worker format = "Docker", 199*c8dee2aaSAndroid Build Coastguard Worker image = image_name, 200*c8dee2aaSAndroid Build Coastguard Worker registry = "gcr.io", 201*c8dee2aaSAndroid Build Coastguard Worker repository = repository, 202*c8dee2aaSAndroid Build Coastguard Worker stamp = "@io_bazel_rules_docker//stamp:always", 203*c8dee2aaSAndroid Build Coastguard Worker tag = "{STABLE_DOCKER_TAG}", 204*c8dee2aaSAndroid Build Coastguard Worker tags = [ 205*c8dee2aaSAndroid Build Coastguard Worker "manual", # Exclude it from wildcard queries, e.g. "bazel build //...". 206*c8dee2aaSAndroid Build Coastguard Worker # container_push requires the docker daemon to be 207*c8dee2aaSAndroid Build Coastguard Worker # running. This is not possible inside RBE. 208*c8dee2aaSAndroid Build Coastguard Worker "no-remote", 209*c8dee2aaSAndroid Build Coastguard Worker ], 210*c8dee2aaSAndroid Build Coastguard Worker ) 211