Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions platform/src/components/aws/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { rpc } from "../rpc/rpc.js";
import { parseRoleArn } from "./helpers/arn.js";
import { RandomBytes } from "@pulumi/random";
import { lazy } from "../../util/lazy.js";
import { requireDocker } from "../../util/docker.js";
import { Efs } from "./efs.js";
import { FunctionEnvironmentUpdate } from "./providers/function-environment-update.js";
import { warnOnce } from "../../util/warn.js";
Expand Down Expand Up @@ -2174,6 +2175,8 @@ export class Function extends Component implements Link.Linkable {
]) => {
if (!isContainer || dev) return;

requireDocker();

const authToken = ecr.getAuthorizationTokenOutput({
registryId: bootstrapData.assetEcrRegistryId,
});
Expand Down
2 changes: 2 additions & 0 deletions platform/src/components/aws/helpers/container-builder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { all, ComponentResourceOptions } from "@pulumi/pulumi";
import { Semaphore } from "../../../util/semaphore";
import { Image, ImageArgs } from "@pulumi/docker-build";
import { requireDocker } from "../../../util/docker";

const limiter = new Semaphore(
parseInt(process.env.SST_BUILD_CONCURRENCY_CONTAINER || "1"),
Expand All @@ -11,6 +12,7 @@ export function imageBuilder(
args: ImageArgs,
opts?: ComponentResourceOptions,
) {
requireDocker();
// Wait for the all args values to be resolved before acquiring the semaphore
return all([args]).apply(async ([args]) => {
await limiter.acquire(name);
Expand Down
2 changes: 2 additions & 0 deletions platform/src/components/aws/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
} from "./fargate.js";
import { Dns } from "../dns.js";
import { hashStringToPrettyString } from "../naming.js";
import { needsLocalDocker, requireDocker } from "../../util/docker.js";

type Port = `${number}/${"http" | "https" | "tcp" | "udp" | "tcp_udp" | "tls"}`;

Expand Down Expand Up @@ -1642,6 +1643,7 @@ export class Service extends Component implements Link.Linkable {
const clusterName = args.cluster.nodes.cluster.name;
const region = getRegionOutput({}, opts).name;
const dev = normalizeDev();
if (!dev && needsLocalDocker(args)) requireDocker();
const wait = output(args.wait ?? false);
const architecture = normalizeArchitecture(args);
const cpu = normalizeCpu(args);
Expand Down
2 changes: 2 additions & 0 deletions platform/src/components/aws/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
normalizeStorage,
} from "./fargate.js";
import { Input } from "../input.js";
import { needsLocalDocker, requireDocker } from "../../util/docker.js";

export interface TaskArgs extends FargateBaseArgs {
/**
Expand Down Expand Up @@ -288,6 +289,7 @@ export class Task extends Component implements Link.Linkable {

const self = this;
const dev = normalizeDev();
if (!dev && needsLocalDocker(args)) requireDocker();
const architecture = normalizeArchitecture(args);
const cpu = normalizeCpu(args);
const memory = normalizeMemory(cpu, args);
Expand Down
48 changes: 48 additions & 0 deletions platform/src/util/docker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { execSync } from "child_process";
import { VisibleError } from "../components/error.js";
import { Input } from "../components/input.js";

let dockerChecked = false;
let dockerAvailable = false;

export function isDockerAvailable(): boolean {
if (dockerChecked) return dockerAvailable;
try {
execSync("docker version", { stdio: "pipe", timeout: 5000 });
dockerAvailable = true;
} catch {
dockerAvailable = false;
}
dockerChecked = true;
return dockerAvailable;
}

export function requireDocker(): void {
if (!isDockerAvailable()) {
throw new VisibleError("Docker is required but not running.");
}
}

type ContainerImage = Input<string | { context?: Input<string> }>;

function isLocalImage(image: ContainerImage | undefined) {
return !!(image && typeof image === "object" && "context" in image);
}

export function needsLocalDocker(args: {
image?: ContainerImage;
containers?: Input<{ image?: ContainerImage }>[];
}) {
const { image, containers } = args;
return (
isLocalImage(image) ||
(Array.isArray(containers) &&
containers.some(
(c) =>
c &&
typeof c === "object" &&
"image" in c &&
isLocalImage(c.image),
))
);
}