mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	fix(docker): handle container name conflict usecase. (#17379)
Drive-by: typo in the JSON docker status field.
This commit is contained in:
		
							parent
							
								
									85a5c690a4
								
							
						
					
					
						commit
						24d3a23a66
					
				| @ -175,7 +175,7 @@ export async function printDockerStatus() { | |||||||
|     dockerEngineRunning: isDockerEngine, |     dockerEngineRunning: isDockerEngine, | ||||||
|     imageName: VRT_IMAGE_NAME, |     imageName: VRT_IMAGE_NAME, | ||||||
|     imageIsPulled, |     imageIsPulled, | ||||||
|     containerWSEndpoing: info?.wsEndpoint ?? '', |     containerWSEndpoint: info?.wsEndpoint ?? '', | ||||||
|     containerVNCEndpoint: info?.vncSession ?? '', |     containerVNCEndpoint: info?.vncSession ?? '', | ||||||
|   }, null, 2)); |   }, null, 2)); | ||||||
| } | } | ||||||
| @ -227,6 +227,40 @@ async function ensurePlaywrightContainerOrDie(): Promise<ContainerInfo> { | |||||||
|   if (info) |   if (info) | ||||||
|     return info; |     return info; | ||||||
| 
 | 
 | ||||||
|  |   // The `npx playwright docker build` command is *NOT GUARANTEED* to produce
 | ||||||
|  |   // images with the same SHA.
 | ||||||
|  |   //
 | ||||||
|  |   // Consider the following sequence of actions:
 | ||||||
|  |   // 1. Build first version of image: `npx playwright docker build`
 | ||||||
|  |   // 2. Run container off the image: `npx playwright docker start`
 | ||||||
|  |   // 3. Build second version of image: `npx playwright docker build`
 | ||||||
|  |   //
 | ||||||
|  |   // Our container auto-detection is based on the parent image SHA.
 | ||||||
|  |   // If the image produced at Step 3 has a different SHA then the one produced on Step 1,
 | ||||||
|  |   // then we **won't be able** to auto-detect the container from Step 2.
 | ||||||
|  |   //
 | ||||||
|  |   // Additionally, we won't be able to launch a new container based off image
 | ||||||
|  |   // from Step 3, since it will have a conflicting container name.
 | ||||||
|  |   //
 | ||||||
|  |   // We check if there's a same-named container running to detect & handle this situation.
 | ||||||
|  |   const hasSameNamedContainer = async () => (await dockerApi.listContainers()).some(container => container.names.includes(VRT_CONTAINER_NAME)); | ||||||
|  |   if (await hasSameNamedContainer()) { | ||||||
|  |     // Since we mark all our containers with labels, we'll be able to stop it.
 | ||||||
|  |     await stopAllPlaywrightContainers(); | ||||||
|  |     // If it wasn't our container, then it was launched manually and has to be
 | ||||||
|  |     // stopped manually as well.
 | ||||||
|  |     if (await hasSameNamedContainer()) { | ||||||
|  |       throw createStacklessError('\n' + utils.wrapInASCIIBox([ | ||||||
|  |         `There is already a container with name ${VRT_CONTAINER_NAME}`, | ||||||
|  |         `Please stop this container manually and rerun tests:`, | ||||||
|  |         ``, | ||||||
|  |         `    docker kill ${VRT_CONTAINER_NAME}`, | ||||||
|  |         ``, | ||||||
|  |         `<3 Playwright Team`, | ||||||
|  |       ].join('\n'), 1)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   await dockerApi.launchContainer({ |   await dockerApi.launchContainer({ | ||||||
|     imageId: pwImage.imageId, |     imageId: pwImage.imageId, | ||||||
|     name: VRT_CONTAINER_NAME, |     name: VRT_CONTAINER_NAME, | ||||||
|  | |||||||
| @ -46,7 +46,9 @@ export async function listContainers(): Promise<DockerContainer[]> { | |||||||
|     containerId: container.Id, |     containerId: container.Id, | ||||||
|     imageId: container.ImageID, |     imageId: container.ImageID, | ||||||
|     state: container.State, |     state: container.State, | ||||||
|     names: container.Names, |     // Note: container names are usually prefixed with '/'.
 | ||||||
|  |     // See https://github.com/moby/moby/issues/6705
 | ||||||
|  |     names: (container.Names ?? []).map((name: string) => name.startsWith('/') ? name.substring(1) : name), | ||||||
|     portBindings: container.Ports?.map((portInfo: any) => ({ |     portBindings: container.Ports?.map((portInfo: any) => ({ | ||||||
|       ip: portInfo.IP, |       ip: portInfo.IP, | ||||||
|       hostPort: portInfo.PublicPort, |       hostPort: portInfo.PublicPort, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Andrey Lushnikov
						Andrey Lushnikov