fix(core): Update isDocker check to return true on kubernetes/containerd (#12603)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2025-01-17 13:10:51 +01:00 committed by GitHub
parent 7ae1483792
commit c55dac66ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 57 additions and 21 deletions

View file

@ -142,20 +142,31 @@ export class InstanceSettings {
} }
/** /**
* Whether this instance is running inside a Docker container. * Whether this instance is running inside a Docker/Podman/Kubernetes container.
*
* Based on: https://github.com/sindresorhus/is-docker
*/ */
@Memoized @Memoized
get isDocker() { get isDocker() {
if (existsSync('/.dockerenv') || existsSync('/run/.containerenv')) return true;
try { try {
return ( const cgroupV1 = readFileSync('/proc/self/cgroup', 'utf8');
existsSync('/.dockerenv') || readFileSync('/proc/self/cgroup', 'utf8').includes('docker') if (
); cgroupV1.includes('docker') ||
} catch { cgroupV1.includes('kubepods') ||
cgroupV1.includes('containerd')
)
return true;
} catch {}
try {
const cgroupV2 = readFileSync('/proc/self/mountinfo', 'utf8');
if (
cgroupV2.includes('docker') ||
cgroupV2.includes('kubelet') ||
cgroupV2.includes('containerd')
)
return true;
} catch {}
return false; return false;
} }
}
update(newSettings: WritableSettings) { update(newSettings: WritableSettings) {
this.save({ ...this.settings, ...newSettings }); this.save({ ...this.settings, ...newSettings });

View file

@ -214,33 +214,58 @@ describe('InstanceSettings', () => {
}); });
it('should return true if /.dockerenv exists', () => { it('should return true if /.dockerenv exists', () => {
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(true); mockFs.existsSync.mockImplementation((path) => path === '/.dockerenv');
expect(settings.isDocker).toBe(true); expect(settings.isDocker).toBe(true);
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv'); expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8'); expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
}); });
it('should return true if /proc/self/cgroup contains docker', () => { it('should return true if /run/.containerenv exists', () => {
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(false); mockFs.existsSync.mockImplementation((path) => path === '/run/.containerenv');
mockFs.readFileSync expect(settings.isDocker).toBe(true);
.calledWith('/proc/self/cgroup', 'utf8') expect(mockFs.existsSync).toHaveBeenCalledWith('/run/.containerenv');
.mockReturnValueOnce('docker cgroup'); expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
});
test.each(['docker', 'kubepods', 'containerd'])(
'should return true if /proc/self/cgroup contains %s',
(str) => {
mockFs.existsSync.mockReturnValueOnce(false);
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce(str);
expect(settings.isDocker).toBe(true); expect(settings.isDocker).toBe(true);
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv'); expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/cgroup', 'utf8'); expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
}); },
);
test.each(['docker', 'kubelet', 'containerd'])(
'should return true if /proc/self/mountinfo contains %s',
(str) => {
mockFs.existsSync.mockReturnValueOnce(false);
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce('');
mockFs.readFileSync.calledWith('/proc/self/mountinfo', 'utf8').mockReturnValueOnce(str);
expect(settings.isDocker).toBe(true);
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/mountinfo', 'utf8');
},
);
it('should return false if no docker indicators are found', () => { it('should return false if no docker indicators are found', () => {
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(false); mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(false);
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce(''); mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce('');
mockFs.readFileSync.calledWith('/proc/self/mountinfo', 'utf8').mockReturnValueOnce('');
expect(settings.isDocker).toBe(false); expect(settings.isDocker).toBe(false);
}); });
it('should return false if checking for docker throws an error', () => { it('should return false if reading any of these files throws an error', () => {
mockFs.existsSync.calledWith('/.dockerenv').mockImplementationOnce(() => { mockFs.existsSync.mockReturnValue(false);
throw new Error('Access denied'); mockFs.readFileSync.mockImplementation(() => {
throw new Error('File not found');
}); });
expect(settings.isDocker).toBe(false); expect(settings.isDocker).toBe(false);
}); });