private void registerWithZooKeeper(CuratorFramework client) {
		try {
			String containerId = containerAttributes.getId();
			String containerPath = Paths.build(Paths.CONTAINERS, containerId);
			Stat containerPathStat = client.checkExists().forPath(containerPath);

			// If the ephemeral node for this container exists, there are two
			// possibilities:
			//   1. The ZooKeeper session for this container was temporarily
			//      suspended and has now resumed. This is usually the case
			//      when a RECONNECTED event is raised after a SUSPENDED
			//      event.
			//   2. A new ZooKeeper session has been created and the existing
			//      ephemeral node has not been cleaned up yet because the
			//      previous session has not expired yet. This may happen
			//      when a RECONNECTED event follows a SUSPENDED event
			//      if Curator decides to recreate the ZooKeeper connection
			//      in the background. This may also happen when ContainerRegistar
			//      forces a new ZooKeeper connection when a RECONNECTED event
			//      follows a LOST event; see ContainerConnectionListener.onResume.
			if (containerPathStat != null) {
				long prevSession = containerPathStat.getEphemeralOwner();
				long currSession = client.getZookeeperClient().getZooKeeper().getSessionId();
				if (prevSession == currSession) {
					// the current session still exists on the server; skip the
					// rest of the registration process
					logger.info(String.format("Existing registration for container %s with session 0x%x detected",
							containerId, currSession));
					return;
				}

				logger.info(String.format("Previous registration for container %s with " +
								"session %x detected; current session: 0x%x",
						containerId, prevSession, currSession));

				// Before proceeding, wait for the server to remove the ephemeral
				// node from the previous session
				int i = 1;
				long startTime = System.currentTimeMillis();
				while (client.checkExists().forPath(containerPath) != null) {
					logger.info("Waiting for container registration cleanup (elapsed time {} seconds)...",
							((System.currentTimeMillis() - startTime) / 1000));
					Thread.sleep(exponentialDelay(i++, 60) * 1000);
				}
			}

			String moduleDeploymentPath = Paths.build(Paths.MODULE_DEPLOYMENTS,
					Paths.ALLOCATED, containerId);

			// if the module deployment path exists, it means this container
			// was previously connected to ZooKeeper and the admin supervisor
			// has yet to complete processing of this container's exit event;
			// therefore the container startup process will block until the
			// admin has cleaned up the module deployment path (see XD-2004)
			int i = 1;
			long startTime = System.currentTimeMillis();
			while (client.checkExists().forPath(moduleDeploymentPath) != null) {
				logger.info("Waiting for supervisor to clean up prior deployments (elapsed time {} seconds)...",
						((System.currentTimeMillis() - startTime) / 1000));
				Thread.sleep(exponentialDelay(i++, 60) * 1000);
			}

			// create the module deployment path before the ephemeral node
			// (which is created via containerRepository) - the latter
			// makes the container "available" for module deployment
			client.create().creatingParentsIfNeeded().forPath(moduleDeploymentPath);

			synchronized (containerAttributes) {
				// reading the container attributes and writing them to
				// the container node must be an atomic operation; see
				// the handling of EmbeddedServletContainerInitializedEvent
				// in onApplicationEvent
				containerRepository.save(new Container(containerId, containerAttributes));
			}

			// if this container is rejoining, clear out the old cache and recreate
			if (deployments != null) {
				try {
					deployments.close();
				}
				catch (Exception e) {
					// this exception can be ignored; logging at trace level
					logger.trace("Exception while closing deployments cache", e);
				}
			}

			deployments = new PathChildrenCache(client, moduleDeploymentPath, true,
					ThreadUtils.newThreadFactory("DeploymentsPathChildrenCache"));
			deployments.getListenable().addListener(deploymentListener);
			deployments.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);

			logger.info("Container {} joined cluster", containerAttributes);
		}
		catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			throw ZooKeeperUtils.wrapThrowable(e);
		}
		catch (Exception e) {
			throw ZooKeeperUtils.wrapThrowable(e);
		}
	}
Write the Container attributes to ZooKeeper in an ephemeral node under {@code /xd/containers}.
spring-xd-dirt/src/main/java/org/springframework/xd/dirt/server/container/ContainerRegistrar.java