Skip to content

Commit b237ad1

Browse files
authored
Merge pull request #389 from marp-team/dont-rely-is-docker-env
Improve Docker detection for better Chromium execution
2 parents 73dc757 + 1b6cc25 commit b237ad1

File tree

12 files changed

+46
-37
lines changed

12 files changed

+46
-37
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Fixed
66

77
- Prevent outputting a warning about `CHROME_PATH` env if fallbacked to Edge ([#388](https://github.com/marp-team/marp-cli/pull/388))
8+
- Improve Docker detection for better Chromium execution within general images ([#389](https://github.com/marp-team/marp-cli/pull/389))
89

910
## v1.4.0 - 2021-08-29
1011

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ RUN addgroup -S marp && adduser -S -g marp marp \
2424
&& chown -R marp:marp /home/marp
2525

2626
USER marp
27-
ENV IS_DOCKER true
27+
ENV CHROME_PATH /usr/bin/chromium-browser
2828

2929
WORKDIR /home/marp/.cli
3030
COPY --chown=marp:marp . /home/marp/.cli/

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const { jsWithBabel } = require('ts-jest/presets')
33
const esModules = [
44
'ansi-regex',
55
'array-union',
6+
'is-docker',
67
'globby',
78
'os-locale',
89
'slash',

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"get-stdin": "^9.0.0",
101101
"globby": "^12.0.1",
102102
"image-size": "^1.0.0",
103+
"is-docker": "^3.0.0",
103104
"jest": "^27.0.6",
104105
"jest-junit": "^12.2.0",
105106
"nanoid": "^3.1.25",

src/config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { keywordsAsArray } from './engine/meta-plugin'
1111
import { error } from './error'
1212
import { TemplateOption } from './templates'
1313
import { Theme, ThemeSet } from './theme'
14+
import { isOfficialImage } from './utils/docker'
1415

1516
type Overwrite<T, U> = Omit<T, Extract<keyof T, keyof U>> & U
1617

@@ -105,9 +106,9 @@ export class MarpCLIConfig {
105106
const preview = (() => {
106107
const p = this.args.preview ?? this.conf.preview ?? false
107108

108-
if (p && process.env.IS_DOCKER) {
109+
if (p && isOfficialImage()) {
109110
warn(
110-
`Preview window cannot show in an official docker image. Preview option was ignored.`
111+
`Preview window cannot show within an official docker image. Preview option was ignored.`
111112
)
112113
return false
113114
}

src/converter.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import templates, {
1818
TemplateResult,
1919
} from './templates/'
2020
import { ThemeSet } from './theme'
21+
import { isOfficialImage } from './utils/docker'
2122
import {
2223
generatePuppeteerDataDirPath,
2324
generatePuppeteerLaunchArgs,
@@ -472,10 +473,10 @@ export class Converter {
472473
)
473474

474475
// Snapd Chromium cannot access from sandbox container to user-land `/tmp`
475-
// directory so create tmp file to home directory if in Linux. (There is
476-
// an exception for an official docker image)
476+
// directory so always create tmp file to home directory if in Linux.
477+
// (There is an exception for an official docker image)
477478
return baseFile.saveTmpFile({
478-
home: process.platform === 'linux' && !process.env.IS_DOCKER,
479+
home: process.platform === 'linux' && !isOfficialImage(),
479480
extension: '.html',
480481
})
481482
})()

src/marp-cli.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { File, FileType } from './file'
99
import { Preview, fileToURI } from './preview'
1010
import { Server } from './server'
1111
import templates from './templates'
12+
import { isOfficialImage } from './utils/docker'
1213
import { resetExecutablePath } from './utils/puppeteer'
1314
import version from './version'
1415
import watcher, { Watcher, notifier } from './watcher'
@@ -104,7 +105,7 @@ export const marpCli = async (
104105
preview: {
105106
alias: 'p',
106107
describe: 'Open preview window',
107-
hidden: !!process.env.IS_DOCKER,
108+
hidden: isOfficialImage(),
108109
group: OptionGroup.Basic,
109110
type: 'boolean',
110111
},

src/utils/docker.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import _isDocker from 'is-docker'
2+
3+
export const isDocker = () => isOfficialImage() || _isDocker()
4+
export const isOfficialImage = () => !!process.env.MARP_USER

src/utils/puppeteer.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import path from 'path'
33
import puppeteer from 'puppeteer-core'
44
import { warn } from '../cli'
55
import { CLIErrorCode, error } from '../error'
6+
import { isDocker } from '../utils/docker'
67
import { findChromeInstallation } from './chrome-finder'
78
import { findEdgeInstallation } from './edge-finder'
89
import { isWSL, resolveWindowsEnv } from './wsl'
@@ -30,11 +31,11 @@ export const generatePuppeteerLaunchArgs = () => {
3031
const args = new Set<string>(['--export-tagged-pdf'])
3132

3233
// Docker environment and WSL environment need to disable sandbox. :(
33-
if (process.env.IS_DOCKER || isWSL()) args.add('--no-sandbox')
34+
if (isDocker() || isWSL()) args.add('--no-sandbox')
3435

3536
// Workaround for Chrome 73 in docker and unit testing with CircleCI
3637
// https://github.com/GoogleChrome/puppeteer/issues/3774
37-
if (process.env.IS_DOCKER || process.env.CI)
38+
if (isDocker() || process.env.CI)
3839
args.add('--disable-features=VizDisplayCompositor')
3940

4041
// Enable DocumentTransition API
@@ -44,15 +45,10 @@ export const generatePuppeteerLaunchArgs = () => {
4445
if (executablePath === false) {
4546
let findChromeError: Error | undefined
4647

47-
if (process.env.IS_DOCKER) {
48-
// Use already known path within Marp CLI official Docker image
49-
executablePath = '/usr/bin/chromium-browser'
50-
} else {
51-
try {
52-
executablePath = findChromeInstallation()
53-
} catch (e) {
54-
if (e instanceof Error) findChromeError = e
55-
}
48+
try {
49+
executablePath = findChromeInstallation()
50+
} catch (e) {
51+
if (e instanceof Error) findChromeError = e
5652
}
5753

5854
if (!executablePath) {

test/marp-cli.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import { Preview } from '../src/preview'
2121
import { Server } from '../src/server'
2222
import { ThemeSet } from '../src/theme'
23+
import * as docker from '../src/utils/docker'
2324
import * as version from '../src/version'
2425
import { Watcher } from '../src/watcher'
2526

@@ -185,10 +186,9 @@ describe('Marp CLI', () => {
185186
})
186187

187188
describe('when CLI is running in an official Docker image', () => {
188-
beforeEach(() => (process.env.IS_DOCKER = '1'))
189-
afterEach(() => delete process.env.IS_DOCKER)
190-
191189
it('does not output help about --preview option', async () => {
190+
jest.spyOn(docker, 'isOfficialImage').mockImplementation(() => true)
191+
192192
expect(await run()).toBe(0)
193193
expect(error).toHaveBeenCalledWith(
194194
expect.not.stringContaining('--preview')
@@ -330,10 +330,8 @@ describe('Marp CLI', () => {
330330
})
331331

332332
describe('when CLI is running in an official Docker image', () => {
333-
beforeEach(() => (process.env.IS_DOCKER = '1'))
334-
afterEach(() => delete process.env.IS_DOCKER)
335-
336333
it('ignores --preview option with warning', async () => {
334+
jest.spyOn(docker, 'isOfficialImage').mockImplementation(() => true)
337335
const warn = jest.spyOn(cli, 'warn').mockImplementation()
338336

339337
await run()
@@ -897,11 +895,10 @@ describe('Marp CLI', () => {
897895
})
898896

899897
describe('when CLI is running in an official Docker image', () => {
900-
beforeEach(() => (process.env.IS_DOCKER = '1'))
901-
afterEach(() => delete process.env.IS_DOCKER)
902-
903898
it('ignores --preview option with warning', async () => {
899+
jest.spyOn(docker, 'isOfficialImage').mockImplementation(() => true)
904900
await marpCli([onePath, '--preview', '--no-output'])
901+
905902
expect(Preview.prototype.open).not.toHaveBeenCalled()
906903
expect(warn).toHaveBeenCalledWith(
907904
expect.stringContaining('Preview option was ignored')

test/utils/puppeteer.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ const puppeteer = (): typeof import('../../src/utils/puppeteer') =>
1515
const chromeFinder = (): typeof import('../../src/utils/chrome-finder') =>
1616
require('../../src/utils/chrome-finder')
1717

18+
const docker = (): typeof import('../../src/utils/docker') =>
19+
require('../../src/utils/docker')
20+
1821
const edgeFinder = (): typeof import('../../src/utils/edge-finder') =>
1922
require('../../src/utils/edge-finder')
2023

@@ -117,17 +120,15 @@ describe('#generatePuppeteerLaunchArgs', () => {
117120
}
118121
})
119122

120-
it('uses specific settings if running in the official Docker image', () => {
121-
try {
122-
process.env.IS_DOCKER = 'true'
123+
it('uses specific settings if running within a Docker container', () => {
124+
jest.spyOn(docker(), 'isDocker').mockImplementation(() => true)
125+
jest
126+
.spyOn(chromeFinder(), 'findChromeInstallation')
127+
.mockImplementation(() => '/usr/bin/chromium')
123128

124-
const args = puppeteer().generatePuppeteerLaunchArgs()
125-
expect(args.executablePath).toBe('/usr/bin/chromium-browser')
126-
expect(args.args).toContain('--no-sandbox')
127-
expect(args.args).toContain('--disable-features=VizDisplayCompositor')
128-
} finally {
129-
delete process.env.IS_DOCKER
130-
}
129+
const args = puppeteer().generatePuppeteerLaunchArgs()
130+
expect(args.args).toContain('--no-sandbox')
131+
expect(args.args).toContain('--disable-features=VizDisplayCompositor')
131132
})
132133

133134
it("ignores puppeteer's --disable-extensions option if defined CHROME_ENABLE_EXTENSIONS environment value", () => {

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4203,6 +4203,11 @@ is-docker@^2.0.0:
42034203
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
42044204
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
42054205

4206+
is-docker@^3.0.0:
4207+
version "3.0.0"
4208+
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200"
4209+
integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==
4210+
42064211
is-expression@^4.0.0:
42074212
version "4.0.0"
42084213
resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-4.0.0.tgz#c33155962abf21d0afd2552514d67d2ec16fd2ab"

0 commit comments

Comments
 (0)